[nostalgia/core/studio] Make handle copy/cut/paste selections off tile lines

This commit is contained in:
Gary Talent 2020-12-06 03:04:03 -06:00
parent 3dee59d048
commit 36e602b2b0
2 changed files with 39 additions and 45 deletions

View File

@ -348,17 +348,11 @@ class PasteClipboardCommand: public QUndoCommand {
}; };
void TileSheetClipboard::add(int idx, int color) { void TileSheetClipboard::addPixel(int color) {
if (m_chunks.size() && m_chunks.back().index + m_chunks.back().size == idx) {
++m_chunks.back().size;
} else {
m_chunks.push_back({idx, 1});
}
m_pixels.push_back(color); m_pixels.push_back(color);
} }
void TileSheetClipboard::clear() { void TileSheetClipboard::clear() {
m_chunks.clear();
m_pixels.clear(); m_pixels.clear();
} }
@ -366,22 +360,17 @@ bool TileSheetClipboard::empty() const {
return m_pixels.empty(); return m_pixels.empty();
} }
void TileSheetClipboard::paste(int targetIdx, QVector<int> *pixels) const { void TileSheetClipboard::pastePixels(common::Point pt, QVector<int> *tgtPixels, int tgtColumns) const {
std::size_t ci = 0; // clipboard index std::size_t srcIdx = 0;
// set prevSrcIdx to current source index, as first iteration is already const auto w = m_p2.x - m_p1.x;
// correct const auto h = m_p2.y - m_p1.y;
int prevSrcIdx = m_chunks.size() ? m_chunks[0].index : 0; for (int x = 0; x <= w; ++x) {
for (std::size_t chunkIdx = 0; chunkIdx < m_chunks.size(); ++chunkIdx) { for (int y = 0; y <= h; ++y) {
const auto &chunk = m_chunks[chunkIdx]; const auto tgtIdx = ptToIdx(pt + common::Point(x, y), tgtColumns);
targetIdx += chunk.index - prevSrcIdx; if (tgtIdx < tgtPixels->size()) {
prevSrcIdx = chunk.index; (*tgtPixels)[tgtIdx] = m_pixels[srcIdx];
const auto targetMod = targetIdx - chunk.index;
for (int i = 0; i < chunk.size; ++i) {
const auto ti = chunk.index + i + targetMod; // target index
if (ti < pixels->size()) {
(*pixels)[ti] = m_pixels[ci];
} }
++ci; ++srcIdx;
} }
} }
} }
@ -616,18 +605,23 @@ void SheetData::cutToClipboard() {
} }
void SheetData::cutToClipboard(TileSheetClipboard *cb) { void SheetData::cutToClipboard(TileSheetClipboard *cb) {
const auto start = ptToIdx(cb->point1(), m_columns); const auto pt1 = cb->point1();
const auto end = ptToIdx(cb->point2(), m_columns); const auto pt2 = cb->point2();
auto apply = std::make_unique<TileSheetClipboard>(); auto apply = std::make_unique<TileSheetClipboard>();
for (int i = start; i <= end; ++i) { for (int x = pt1.x; x <= pt2.x; ++x) {
for (int y = pt1.y; y <= pt2.y; ++y) {
const auto pt = common::Point(x, y);
const auto i = ptToIdx(pt, m_columns);
const auto s = m_pixelSelected[i]; const auto s = m_pixelSelected[i];
if (s) { if (s) {
cb->add(i, m_pixels[i]); cb->addPixel(m_pixels[i]);
apply->add(i, 0); apply->addPixel(0);
}
} }
} }
apply->setPoints(cb->point1(), cb->point2()); apply->setPoints(cb->point1(), cb->point2());
m_cmdStack->push(new PasteClipboardCommand(this, std::make_unique<TileSheetClipboard>(*cb), std::move(apply))); auto restore = std::make_unique<TileSheetClipboard>(*cb);
m_cmdStack->push(new PasteClipboardCommand(this, std::move(restore), std::move(apply)));
} }
void SheetData::copyToClipboard() { void SheetData::copyToClipboard() {
@ -636,12 +630,13 @@ void SheetData::copyToClipboard() {
} }
void SheetData::copyToClipboard(TileSheetClipboard *cb) { void SheetData::copyToClipboard(TileSheetClipboard *cb) {
const auto start = ptToIdx(cb->point1(), m_columns); const auto p1 = cb->point1();
const auto end = ptToIdx(cb->point2(), m_columns); const auto p2 = cb->point2();
for (int i = start; i <= end; ++i) { for (int x = p1.x; x <= p2.x; ++x) {
const auto s = m_pixelSelected[i]; for (int y = p1.y; y <= p2.y; ++y) {
if (s) { const auto pt = common::Point(x, y);
cb->add(i, m_pixels[i]); const auto idx = ptToIdx(pt, m_columns);
cb->addPixel(m_pixels[idx]);
} }
} }
} }
@ -658,8 +653,7 @@ void SheetData::pasteClipboard() {
} }
void SheetData::applyClipboard(const TileSheetClipboard &cb) { void SheetData::applyClipboard(const TileSheetClipboard &cb) {
const auto idx = ptToIdx(cb.point1(), m_columns); cb.pastePixels(cb.point1(), &m_pixels, m_columns);
cb.paste(idx, &m_pixels);
emit pixelsChanged(); emit pixelsChanged();
emit changeOccurred(); emit changeOccurred();
} }

View File

@ -51,40 +51,39 @@ struct PixelChunk {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.studio.PixelChunk"; static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.studio.PixelChunk";
static constexpr auto Fields = 2; static constexpr auto Fields = 2;
static constexpr auto TypeVersion = 1; static constexpr auto TypeVersion = 1;
int index = -1; common::Point pt;
int size = 0; int size = 0;
}; };
template<typename T> template<typename T>
ox::Error model(T *io, PixelChunk *c) { ox::Error model(T *io, PixelChunk *c) {
io->template setTypeInfo<PixelChunk>(); io->template setTypeInfo<PixelChunk>();
oxReturnError(io->field("index", &c->index)); oxReturnError(io->field("pt", &c->pt));
oxReturnError(io->field("size", &c->size)); oxReturnError(io->field("size", &c->size));
return OxError(0); return OxError(0);
} }
struct TileSheetClipboard { struct TileSheetClipboard {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.studio.TileSheetClipboard"; static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.studio.TileSheetClipboard";
static constexpr auto Fields = 2; static constexpr auto Fields = 3;
static constexpr auto TypeVersion = 1; static constexpr auto TypeVersion = 1;
template<typename T> template<typename T>
friend ox::Error model(T*, TileSheetClipboard*); friend ox::Error model(T*, TileSheetClipboard*);
protected: protected:
std::vector<PixelChunk> m_chunks;
std::vector<int> m_pixels; std::vector<int> m_pixels;
common::Point m_p1; common::Point m_p1;
common::Point m_p2; common::Point m_p2;
public: public:
void add(int idx, int color); void addPixel(int color);
void clear(); void clear();
[[nodiscard]] bool empty() const; [[nodiscard]] bool empty() const;
void paste(int targetIdx, QVector<int> *pixels) const; void pastePixels(common::Point pt, QVector<int> *tgt, int tgtColumns) const;
void setPoints(common::Point p1, common::Point p2); void setPoints(common::Point p1, common::Point p2);
@ -97,8 +96,9 @@ struct TileSheetClipboard {
template<typename T> template<typename T>
ox::Error model(T *io, TileSheetClipboard *b) { ox::Error model(T *io, TileSheetClipboard *b) {
io->template setTypeInfo<TileSheetClipboard>(); io->template setTypeInfo<TileSheetClipboard>();
oxReturnError(io->field("chunks", &b->m_chunks));
oxReturnError(io->field("pixels", &b->m_pixels)); oxReturnError(io->field("pixels", &b->m_pixels));
oxReturnError(io->field("p1", &b->m_p1));
oxReturnError(io->field("p2", &b->m_p2));
return OxError(0); return OxError(0);
} }