[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) {
|
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();
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user