[nostalgia/core/studio/tilesheet] Add ability to rotate a selection
This commit is contained in:
parent
fb8d295fcb
commit
1bc18e34a8
@ -6,50 +6,58 @@
|
|||||||
|
|
||||||
namespace nostalgia::gfx {
|
namespace nostalgia::gfx {
|
||||||
|
|
||||||
static void rotateLeft(TileSheet::SubSheet &ss, ox::Point const &pt, int const depth = 0) noexcept {
|
static void rotateLeft(
|
||||||
|
TileSheet::SubSheet &ss,
|
||||||
|
ox::Point const &pt,
|
||||||
|
ox::Point const &pt1,
|
||||||
|
ox::Point const &pt2,
|
||||||
|
int const depth = 0) noexcept {
|
||||||
if (depth >= 4) {
|
if (depth >= 4) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto const h = ss.rows * TileHeight;
|
auto const dstPt = ox::Point{pt1.x + pt.y, pt2.y - pt.x};
|
||||||
auto const dstPt = ox::Point{pt.y, h - 1 - pt.x};
|
auto const srcIdx = ptToIdx(pt + pt1, ss.columns);
|
||||||
auto const srcIdx = ptToIdx(pt, ss.columns);
|
|
||||||
auto const dstIdx = ptToIdx(dstPt, ss.columns);
|
auto const dstIdx = ptToIdx(dstPt, ss.columns);
|
||||||
auto const src = ss.pixels[srcIdx];
|
auto const src = ss.pixels[srcIdx];
|
||||||
auto &dst = ss.pixels[dstIdx];
|
auto &dst = ss.pixels[dstIdx];
|
||||||
rotateLeft(ss, dstPt, depth + 1);
|
rotateLeft(ss, dstPt - pt1, pt1, pt2, depth + 1);
|
||||||
dst = src;
|
dst = src;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rotateLeft(TileSheet::SubSheet &ss) noexcept {
|
static void rotateLeft(TileSheet::SubSheet &ss, ox::Point const &pt1, ox::Point const &pt2) noexcept {
|
||||||
auto const w = ss.columns * TileWidth;
|
auto const w = pt2.x - pt1.x;
|
||||||
auto const h = ss.rows * TileHeight;
|
auto const h = pt2.y - pt1.y;
|
||||||
for (int x = 0; x < w / 2; ++x) {
|
for (int x = 0; x <= w / 2; ++x) {
|
||||||
for (int y = 0; y < h / 2; ++y) {
|
for (int y = 0; y <= h / 2; ++y) {
|
||||||
rotateLeft(ss, {w - 1 - y, x});
|
rotateLeft(ss, {x, y}, pt1, pt2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rotateRight(TileSheet::SubSheet &ss, ox::Point const &pt, int const depth = 0) noexcept {
|
static void rotateRight(
|
||||||
|
TileSheet::SubSheet &ss,
|
||||||
|
ox::Point const &pt,
|
||||||
|
ox::Point const &pt1,
|
||||||
|
ox::Point const &pt2,
|
||||||
|
int const depth = 0) noexcept {
|
||||||
if (depth >= 4) {
|
if (depth >= 4) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto const w = ss.columns * TileWidth;
|
auto const dstPt = ox::Point{pt2.x - pt.y, pt1.y + pt.x};
|
||||||
auto const dstPt = ox::Point{w - 1 - pt.y, pt.x};
|
auto const srcIdx = ptToIdx(pt + pt1, ss.columns);
|
||||||
auto const srcIdx = ptToIdx(pt, ss.columns);
|
|
||||||
auto const dstIdx = ptToIdx(dstPt, ss.columns);
|
auto const dstIdx = ptToIdx(dstPt, ss.columns);
|
||||||
auto const src = ss.pixels[srcIdx];
|
auto const src = ss.pixels[srcIdx];
|
||||||
auto &dst = ss.pixels[dstIdx];
|
auto &dst = ss.pixels[dstIdx];
|
||||||
rotateRight(ss, dstPt, depth + 1);
|
rotateRight(ss, dstPt - pt1, pt1, pt2, depth + 1);
|
||||||
dst = src;
|
dst = src;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rotateRight(TileSheet::SubSheet &ss) noexcept {
|
static void rotateRight(TileSheet::SubSheet &ss, ox::Point const &pt1, ox::Point const &pt2) noexcept {
|
||||||
auto const w = ss.columns * TileWidth;
|
auto const w = pt2.x - pt1.x;
|
||||||
auto const h = ss.rows * TileHeight;
|
auto const h = pt2.y - pt1.y;
|
||||||
for (int x = 0; x < w / 2; ++x) {
|
for (int x = 0; x <= w / 2; ++x) {
|
||||||
for (int y = 0; y < h / 2; ++y) {
|
for (int y = 0; y <= h / 2; ++y) {
|
||||||
rotateRight(ss, {w - 1 - y, x});
|
rotateRight(ss, {x, y}, pt1, pt2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -61,28 +69,47 @@ RotateCommand::RotateCommand(
|
|||||||
Direction const dir) noexcept:
|
Direction const dir) noexcept:
|
||||||
m_img(img),
|
m_img(img),
|
||||||
m_idx(std::move(idx)),
|
m_idx(std::move(idx)),
|
||||||
|
m_pt2{[this] {
|
||||||
|
auto &ss = getSubSheet(m_img, m_idx);
|
||||||
|
return ox::Point{ss.columns * TileWidth - 1, ss.rows * TileHeight - 1};
|
||||||
|
}()},
|
||||||
|
m_dir{dir} {
|
||||||
|
}
|
||||||
|
|
||||||
|
RotateCommand::RotateCommand(
|
||||||
|
TileSheet &img,
|
||||||
|
TileSheet::SubSheetIdx idx,
|
||||||
|
ox::Point const &pt1,
|
||||||
|
ox::Point const &pt2,
|
||||||
|
Direction const dir) noexcept:
|
||||||
|
m_img(img),
|
||||||
|
m_idx(std::move(idx)),
|
||||||
|
m_pt1{pt1},
|
||||||
|
m_pt2{pt2},
|
||||||
m_dir{dir} {
|
m_dir{dir} {
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Error RotateCommand::redo() noexcept {
|
ox::Error RotateCommand::redo() noexcept {
|
||||||
|
auto &ss = getSubSheet(m_img, m_idx);
|
||||||
switch (m_dir) {
|
switch (m_dir) {
|
||||||
case Direction::Left:
|
case Direction::Left:
|
||||||
rotateLeft(getSubSheet(m_img, m_idx));
|
rotateLeft(ss, m_pt1, m_pt2);
|
||||||
break;
|
break;
|
||||||
case Direction::Right:
|
case Direction::Right:
|
||||||
rotateRight(getSubSheet(m_img, m_idx));
|
rotateRight(ss, m_pt1, m_pt2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Error RotateCommand::undo() noexcept {
|
ox::Error RotateCommand::undo() noexcept {
|
||||||
|
auto &ss = getSubSheet(m_img, m_idx);
|
||||||
switch (m_dir) {
|
switch (m_dir) {
|
||||||
case Direction::Left:
|
case Direction::Left:
|
||||||
rotateRight(getSubSheet(m_img, m_idx));
|
rotateRight(ss, m_pt1, m_pt2);
|
||||||
break;
|
break;
|
||||||
case Direction::Right:
|
case Direction::Right:
|
||||||
rotateLeft(getSubSheet(m_img, m_idx));
|
rotateLeft(ss, m_pt1, m_pt2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
|
@ -18,11 +18,20 @@ class RotateCommand: public TileSheetCommand {
|
|||||||
private:
|
private:
|
||||||
TileSheet &m_img;
|
TileSheet &m_img;
|
||||||
TileSheet::SubSheetIdx m_idx;
|
TileSheet::SubSheetIdx m_idx;
|
||||||
|
ox::Point const m_pt1;
|
||||||
|
ox::Point const m_pt2;
|
||||||
Direction const m_dir;
|
Direction const m_dir;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RotateCommand(TileSheet &img, TileSheet::SubSheetIdx idx, Direction dir) noexcept;
|
RotateCommand(TileSheet &img, TileSheet::SubSheetIdx idx, Direction dir) noexcept;
|
||||||
|
|
||||||
|
RotateCommand(
|
||||||
|
TileSheet &img,
|
||||||
|
TileSheet::SubSheetIdx idx,
|
||||||
|
ox::Point const &pt1,
|
||||||
|
ox::Point const &pt2,
|
||||||
|
Direction dir) noexcept;
|
||||||
|
|
||||||
ox::Error redo() noexcept final;
|
ox::Error redo() noexcept final;
|
||||||
|
|
||||||
ox::Error undo() noexcept final;
|
ox::Error undo() noexcept final;
|
||||||
|
@ -239,13 +239,25 @@ void TileSheetEditorModel::fill(ox::Point const&pt, int const palIdx) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ox::Error TileSheetEditorModel::rotateLeft() noexcept {
|
ox::Error TileSheetEditorModel::rotateLeft() noexcept {
|
||||||
|
auto &ss = activeSubSheet();
|
||||||
|
ox::Point pt1, pt2{ss.columns * TileWidth - 1, ss.rows * TileHeight - 1};
|
||||||
|
if (m_selection) {
|
||||||
|
pt1 = m_selection->a;
|
||||||
|
pt2 = m_selection->b;
|
||||||
|
}
|
||||||
return pushCommand(ox::make<RotateCommand>(
|
return pushCommand(ox::make<RotateCommand>(
|
||||||
m_img, m_activeSubsSheetIdx, RotateCommand::Direction::Left));
|
m_img, m_activeSubsSheetIdx, pt1, pt2, RotateCommand::Direction::Left));
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Error TileSheetEditorModel::rotateRight() noexcept {
|
ox::Error TileSheetEditorModel::rotateRight() noexcept {
|
||||||
|
auto &ss = activeSubSheet();
|
||||||
|
ox::Point pt1, pt2{ss.columns * TileWidth - 1, ss.rows * TileHeight - 1};
|
||||||
|
if (m_selection) {
|
||||||
|
pt1 = m_selection->a;
|
||||||
|
pt2 = m_selection->b;
|
||||||
|
}
|
||||||
return pushCommand(ox::make<RotateCommand>(
|
return pushCommand(ox::make<RotateCommand>(
|
||||||
m_img, m_activeSubsSheetIdx, RotateCommand::Direction::Right));
|
m_img, m_activeSubsSheetIdx, pt1, pt2, RotateCommand::Direction::Right));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileSheetEditorModel::setSelection(studio::Selection const&sel) noexcept {
|
void TileSheetEditorModel::setSelection(studio::Selection const&sel) noexcept {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user