[nostalgia/core/studio] Make handle copy/cut/paste selections off tile lines
This commit is contained in:
parent
3dee59d048
commit
36e602b2b0
@ -348,17 +348,11 @@ class PasteClipboardCommand: public QUndoCommand {
|
||||
};
|
||||
|
||||
|
||||
void TileSheetClipboard::add(int idx, 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});
|
||||
}
|
||||
void TileSheetClipboard::addPixel(int color) {
|
||||
m_pixels.push_back(color);
|
||||
}
|
||||
|
||||
void TileSheetClipboard::clear() {
|
||||
m_chunks.clear();
|
||||
m_pixels.clear();
|
||||
}
|
||||
|
||||
@ -366,22 +360,17 @@ bool TileSheetClipboard::empty() const {
|
||||
return m_pixels.empty();
|
||||
}
|
||||
|
||||
void TileSheetClipboard::paste(int targetIdx, QVector<int> *pixels) const {
|
||||
std::size_t ci = 0; // clipboard index
|
||||
// set prevSrcIdx to current source index, as first iteration is already
|
||||
// correct
|
||||
int prevSrcIdx = m_chunks.size() ? m_chunks[0].index : 0;
|
||||
for (std::size_t chunkIdx = 0; chunkIdx < m_chunks.size(); ++chunkIdx) {
|
||||
const auto &chunk = m_chunks[chunkIdx];
|
||||
targetIdx += chunk.index - prevSrcIdx;
|
||||
prevSrcIdx = chunk.index;
|
||||
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];
|
||||
void TileSheetClipboard::pastePixels(common::Point pt, QVector<int> *tgtPixels, int tgtColumns) const {
|
||||
std::size_t srcIdx = 0;
|
||||
const auto w = m_p2.x - m_p1.x;
|
||||
const auto h = m_p2.y - m_p1.y;
|
||||
for (int x = 0; x <= w; ++x) {
|
||||
for (int y = 0; y <= h; ++y) {
|
||||
const auto tgtIdx = ptToIdx(pt + common::Point(x, y), tgtColumns);
|
||||
if (tgtIdx < tgtPixels->size()) {
|
||||
(*tgtPixels)[tgtIdx] = m_pixels[srcIdx];
|
||||
}
|
||||
++ci;
|
||||
++srcIdx;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -616,18 +605,23 @@ void SheetData::cutToClipboard() {
|
||||
}
|
||||
|
||||
void SheetData::cutToClipboard(TileSheetClipboard *cb) {
|
||||
const auto start = ptToIdx(cb->point1(), m_columns);
|
||||
const auto end = ptToIdx(cb->point2(), m_columns);
|
||||
const auto pt1 = cb->point1();
|
||||
const auto pt2 = cb->point2();
|
||||
auto apply = std::make_unique<TileSheetClipboard>();
|
||||
for (int i = start; i <= end; ++i) {
|
||||
const auto s = m_pixelSelected[i];
|
||||
if (s) {
|
||||
cb->add(i, m_pixels[i]);
|
||||
apply->add(i, 0);
|
||||
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];
|
||||
if (s) {
|
||||
cb->addPixel(m_pixels[i]);
|
||||
apply->addPixel(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
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() {
|
||||
@ -636,12 +630,13 @@ void SheetData::copyToClipboard() {
|
||||
}
|
||||
|
||||
void SheetData::copyToClipboard(TileSheetClipboard *cb) {
|
||||
const auto start = ptToIdx(cb->point1(), m_columns);
|
||||
const auto end = ptToIdx(cb->point2(), m_columns);
|
||||
for (int i = start; i <= end; ++i) {
|
||||
const auto s = m_pixelSelected[i];
|
||||
if (s) {
|
||||
cb->add(i, m_pixels[i]);
|
||||
const auto p1 = cb->point1();
|
||||
const auto p2 = cb->point2();
|
||||
for (int x = p1.x; x <= p2.x; ++x) {
|
||||
for (int y = p1.y; y <= p2.y; ++y) {
|
||||
const auto pt = common::Point(x, y);
|
||||
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) {
|
||||
const auto idx = ptToIdx(cb.point1(), m_columns);
|
||||
cb.paste(idx, &m_pixels);
|
||||
cb.pastePixels(cb.point1(), &m_pixels, m_columns);
|
||||
emit pixelsChanged();
|
||||
emit changeOccurred();
|
||||
}
|
||||
|
@ -51,40 +51,39 @@ struct PixelChunk {
|
||||
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.studio.PixelChunk";
|
||||
static constexpr auto Fields = 2;
|
||||
static constexpr auto TypeVersion = 1;
|
||||
int index = -1;
|
||||
common::Point pt;
|
||||
int size = 0;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
ox::Error model(T *io, PixelChunk *c) {
|
||||
io->template setTypeInfo<PixelChunk>();
|
||||
oxReturnError(io->field("index", &c->index));
|
||||
oxReturnError(io->field("pt", &c->pt));
|
||||
oxReturnError(io->field("size", &c->size));
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
struct 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;
|
||||
|
||||
template<typename T>
|
||||
friend ox::Error model(T*, TileSheetClipboard*);
|
||||
|
||||
protected:
|
||||
std::vector<PixelChunk> m_chunks;
|
||||
std::vector<int> m_pixels;
|
||||
common::Point m_p1;
|
||||
common::Point m_p2;
|
||||
|
||||
public:
|
||||
void add(int idx, int color);
|
||||
void addPixel(int color);
|
||||
|
||||
void clear();
|
||||
|
||||
[[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);
|
||||
|
||||
@ -97,8 +96,9 @@ struct TileSheetClipboard {
|
||||
template<typename T>
|
||||
ox::Error model(T *io, TileSheetClipboard *b) {
|
||||
io->template setTypeInfo<TileSheetClipboard>();
|
||||
oxReturnError(io->field("chunks", &b->m_chunks));
|
||||
oxReturnError(io->field("pixels", &b->m_pixels));
|
||||
oxReturnError(io->field("p1", &b->m_p1));
|
||||
oxReturnError(io->field("p2", &b->m_p2));
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user