[nostalgia/core/studio/tilesheet] Add rotate functionality
This commit is contained in:
parent
804d78e116
commit
fb8d295fcb
@ -9,5 +9,6 @@ target_sources(
|
|||||||
inserttilescommand.cpp
|
inserttilescommand.cpp
|
||||||
palettechangecommand.cpp
|
palettechangecommand.cpp
|
||||||
rmsubsheetcommand.cpp
|
rmsubsheetcommand.cpp
|
||||||
|
rotatecommand.cpp
|
||||||
updatesubsheetcommand.cpp
|
updatesubsheetcommand.cpp
|
||||||
)
|
)
|
||||||
|
@ -17,6 +17,7 @@ enum class CommandId {
|
|||||||
DeleteTile,
|
DeleteTile,
|
||||||
FlipX,
|
FlipX,
|
||||||
FlipY,
|
FlipY,
|
||||||
|
Rotate,
|
||||||
InsertTile,
|
InsertTile,
|
||||||
MoveSubSheet,
|
MoveSubSheet,
|
||||||
UpdateSubSheet,
|
UpdateSubSheet,
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
namespace nostalgia::gfx {
|
namespace nostalgia::gfx {
|
||||||
|
|
||||||
gfx::RmSubSheetCommand::RmSubSheetCommand(TileSheet &img, TileSheet::SubSheetIdx idx) noexcept:
|
RmSubSheetCommand::RmSubSheetCommand(TileSheet &img, TileSheet::SubSheetIdx idx) noexcept:
|
||||||
m_img(img),
|
m_img(img),
|
||||||
m_idx(std::move(idx)),
|
m_idx(std::move(idx)),
|
||||||
m_parentIdx(m_idx) {
|
m_parentIdx(m_idx) {
|
||||||
|
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "rotatecommand.hpp"
|
||||||
|
|
||||||
|
namespace nostalgia::gfx {
|
||||||
|
|
||||||
|
static void rotateLeft(TileSheet::SubSheet &ss, ox::Point const &pt, int const depth = 0) noexcept {
|
||||||
|
if (depth >= 4) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto const h = ss.rows * TileHeight;
|
||||||
|
auto const dstPt = ox::Point{pt.y, h - 1 - pt.x};
|
||||||
|
auto const srcIdx = ptToIdx(pt, ss.columns);
|
||||||
|
auto const dstIdx = ptToIdx(dstPt, ss.columns);
|
||||||
|
auto const src = ss.pixels[srcIdx];
|
||||||
|
auto &dst = ss.pixels[dstIdx];
|
||||||
|
rotateLeft(ss, dstPt, depth + 1);
|
||||||
|
dst = src;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rotateLeft(TileSheet::SubSheet &ss) noexcept {
|
||||||
|
auto const w = ss.columns * TileWidth;
|
||||||
|
auto const h = ss.rows * TileHeight;
|
||||||
|
for (int x = 0; x < w / 2; ++x) {
|
||||||
|
for (int y = 0; y < h / 2; ++y) {
|
||||||
|
rotateLeft(ss, {w - 1 - y, x});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rotateRight(TileSheet::SubSheet &ss, ox::Point const &pt, int const depth = 0) noexcept {
|
||||||
|
if (depth >= 4) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto const w = ss.columns * TileWidth;
|
||||||
|
auto const dstPt = ox::Point{w - 1 - pt.y, pt.x};
|
||||||
|
auto const srcIdx = ptToIdx(pt, ss.columns);
|
||||||
|
auto const dstIdx = ptToIdx(dstPt, ss.columns);
|
||||||
|
auto const src = ss.pixels[srcIdx];
|
||||||
|
auto &dst = ss.pixels[dstIdx];
|
||||||
|
rotateRight(ss, dstPt, depth + 1);
|
||||||
|
dst = src;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rotateRight(TileSheet::SubSheet &ss) noexcept {
|
||||||
|
auto const w = ss.columns * TileWidth;
|
||||||
|
auto const h = ss.rows * TileHeight;
|
||||||
|
for (int x = 0; x < w / 2; ++x) {
|
||||||
|
for (int y = 0; y < h / 2; ++y) {
|
||||||
|
rotateRight(ss, {w - 1 - y, x});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RotateCommand::RotateCommand(
|
||||||
|
TileSheet &img,
|
||||||
|
TileSheet::SubSheetIdx idx,
|
||||||
|
Direction const dir) noexcept:
|
||||||
|
m_img(img),
|
||||||
|
m_idx(std::move(idx)),
|
||||||
|
m_dir{dir} {
|
||||||
|
}
|
||||||
|
|
||||||
|
ox::Error RotateCommand::redo() noexcept {
|
||||||
|
switch (m_dir) {
|
||||||
|
case Direction::Left:
|
||||||
|
rotateLeft(getSubSheet(m_img, m_idx));
|
||||||
|
break;
|
||||||
|
case Direction::Right:
|
||||||
|
rotateRight(getSubSheet(m_img, m_idx));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
ox::Error RotateCommand::undo() noexcept {
|
||||||
|
switch (m_dir) {
|
||||||
|
case Direction::Left:
|
||||||
|
rotateRight(getSubSheet(m_img, m_idx));
|
||||||
|
break;
|
||||||
|
case Direction::Right:
|
||||||
|
rotateLeft(getSubSheet(m_img, m_idx));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
int RotateCommand::commandId() const noexcept {
|
||||||
|
return static_cast<int>(CommandId::Rotate);
|
||||||
|
}
|
||||||
|
|
||||||
|
TileSheet::SubSheetIdx const&RotateCommand::subsheetIdx() const noexcept {
|
||||||
|
return m_idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "commands.hpp"
|
||||||
|
|
||||||
|
namespace nostalgia::gfx {
|
||||||
|
|
||||||
|
class RotateCommand: public TileSheetCommand {
|
||||||
|
public:
|
||||||
|
enum class Direction {
|
||||||
|
Right,
|
||||||
|
Left,
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
TileSheet &m_img;
|
||||||
|
TileSheet::SubSheetIdx m_idx;
|
||||||
|
Direction const m_dir;
|
||||||
|
|
||||||
|
public:
|
||||||
|
RotateCommand(TileSheet &img, TileSheet::SubSheetIdx idx, Direction dir) noexcept;
|
||||||
|
|
||||||
|
ox::Error redo() noexcept final;
|
||||||
|
|
||||||
|
ox::Error undo() noexcept final;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
int commandId() const noexcept final;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
TileSheet::SubSheetIdx const&subsheetIdx() const noexcept override;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -248,14 +248,22 @@ void TileSheetEditorImGui::draw(studio::StudioContext&) noexcept {
|
|||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
ImGui::BeginChild("OperationsBox", {0, 32}, true);
|
ImGui::BeginChild("OperationsBox", {0, 32}, true);
|
||||||
{
|
{
|
||||||
auto constexpr btnSz = ImVec2{55, 16};
|
auto constexpr btnSz = ImVec2{75, 16};
|
||||||
if (ig::PushButton("Flip X", btnSz)) {
|
if (ig::PushButton("Flip X", {55, 16})) {
|
||||||
oxLogError(m_model.flipX());
|
oxLogError(m_model.flipX());
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ig::PushButton("Flip Y", btnSz)) {
|
if (ig::PushButton("Flip Y", {55, 16})) {
|
||||||
oxLogError(m_model.flipY());
|
oxLogError(m_model.flipY());
|
||||||
}
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ig::PushButton("Rotate Left", {80, 16})) {
|
||||||
|
oxLogError(m_model.rotateLeft());
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ig::PushButton("Rotate Right", {80, 16})) {
|
||||||
|
oxLogError(m_model.rotateRight());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
auto const ySize = controlsSize.y - (38 + ig::BtnSz.y + 21);
|
auto const ySize = controlsSize.y - (38 + ig::BtnSz.y + 21);
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "tilesheeteditormodel.hpp"
|
#include "tilesheeteditormodel.hpp"
|
||||||
|
|
||||||
#include "commands/movesubsheetcommand.hpp"
|
#include "commands/movesubsheetcommand.hpp"
|
||||||
|
#include "commands/rotatecommand.hpp"
|
||||||
|
|
||||||
namespace nostalgia::gfx {
|
namespace nostalgia::gfx {
|
||||||
|
|
||||||
@ -237,6 +238,16 @@ void TileSheetEditorModel::fill(ox::Point const&pt, int const palIdx) noexcept {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ox::Error TileSheetEditorModel::rotateLeft() noexcept {
|
||||||
|
return pushCommand(ox::make<RotateCommand>(
|
||||||
|
m_img, m_activeSubsSheetIdx, RotateCommand::Direction::Left));
|
||||||
|
}
|
||||||
|
|
||||||
|
ox::Error TileSheetEditorModel::rotateRight() noexcept {
|
||||||
|
return pushCommand(ox::make<RotateCommand>(
|
||||||
|
m_img, m_activeSubsSheetIdx, RotateCommand::Direction::Right));
|
||||||
|
}
|
||||||
|
|
||||||
void TileSheetEditorModel::setSelection(studio::Selection const&sel) noexcept {
|
void TileSheetEditorModel::setSelection(studio::Selection const&sel) noexcept {
|
||||||
m_selection.emplace(sel);
|
m_selection.emplace(sel);
|
||||||
m_updated = true;
|
m_updated = true;
|
||||||
|
@ -106,6 +106,10 @@ class TileSheetEditorModel: public ox::SignalHandler {
|
|||||||
|
|
||||||
void fill(ox::Point const&pt, int palIdx) noexcept;
|
void fill(ox::Point const&pt, int palIdx) noexcept;
|
||||||
|
|
||||||
|
ox::Error rotateLeft() noexcept;
|
||||||
|
|
||||||
|
ox::Error rotateRight() noexcept;
|
||||||
|
|
||||||
void setSelection(studio::Selection const&sel) noexcept;
|
void setSelection(studio::Selection const&sel) noexcept;
|
||||||
|
|
||||||
void select(ox::Point const&pt) noexcept;
|
void select(ox::Point const&pt) noexcept;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user