Compare commits
3 Commits
804d78e116
...
105a1e5559
| Author | SHA1 | Date | |
|---|---|---|---|
| 105a1e5559 | |||
| 1bc18e34a8 | |||
| fb8d295fcb |
@@ -9,5 +9,6 @@ target_sources(
|
||||
inserttilescommand.cpp
|
||||
palettechangecommand.cpp
|
||||
rmsubsheetcommand.cpp
|
||||
rotatecommand.cpp
|
||||
updatesubsheetcommand.cpp
|
||||
)
|
||||
|
||||
@@ -17,6 +17,7 @@ enum class CommandId {
|
||||
DeleteTile,
|
||||
FlipX,
|
||||
FlipY,
|
||||
Rotate,
|
||||
InsertTile,
|
||||
MoveSubSheet,
|
||||
UpdateSubSheet,
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
namespace nostalgia::gfx {
|
||||
|
||||
gfx::RmSubSheetCommand::RmSubSheetCommand(TileSheet &img, TileSheet::SubSheetIdx idx) noexcept:
|
||||
RmSubSheetCommand::RmSubSheetCommand(TileSheet &img, TileSheet::SubSheetIdx idx) noexcept:
|
||||
m_img(img),
|
||||
m_idx(std::move(idx)),
|
||||
m_parentIdx(m_idx) {
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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,
|
||||
ox::Point const &pt1,
|
||||
ox::Point const &pt2,
|
||||
int const depth = 0) noexcept {
|
||||
if (depth >= 4) {
|
||||
return;
|
||||
}
|
||||
auto const dstPt = ox::Point{pt1.x + pt.y, pt2.y - pt.x};
|
||||
auto const srcIdx = ptToIdx(pt + pt1, ss.columns);
|
||||
auto const dstIdx = ptToIdx(dstPt, ss.columns);
|
||||
auto const src = ss.pixels[srcIdx];
|
||||
auto &dst = ss.pixels[dstIdx];
|
||||
rotateLeft(ss, dstPt - pt1, pt1, pt2, depth + 1);
|
||||
dst = src;
|
||||
}
|
||||
|
||||
static void rotateLeft(TileSheet::SubSheet &ss, ox::Point const &pt1, ox::Point const &pt2) noexcept {
|
||||
auto const w = pt2.x - pt1.x;
|
||||
auto const h = pt2.y - pt1.y;
|
||||
for (int x = 0; x <= w / 2; ++x) {
|
||||
for (int y = 0; y <= h / 2; ++y) {
|
||||
rotateLeft(ss, {x, y}, pt1, pt2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
auto const dstPt = ox::Point{pt2.x - pt.y, pt1.y + pt.x};
|
||||
auto const srcIdx = ptToIdx(pt + pt1, ss.columns);
|
||||
auto const dstIdx = ptToIdx(dstPt, ss.columns);
|
||||
auto const src = ss.pixels[srcIdx];
|
||||
auto &dst = ss.pixels[dstIdx];
|
||||
rotateRight(ss, dstPt - pt1, pt1, pt2, depth + 1);
|
||||
dst = src;
|
||||
}
|
||||
|
||||
static void rotateRight(TileSheet::SubSheet &ss, ox::Point const &pt1, ox::Point const &pt2) noexcept {
|
||||
auto const w = pt2.x - pt1.x;
|
||||
auto const h = pt2.y - pt1.y;
|
||||
for (int x = 0; x <= w / 2; ++x) {
|
||||
for (int y = 0; y <= h / 2; ++y) {
|
||||
rotateRight(ss, {x, y}, pt1, pt2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RotateCommand::RotateCommand(
|
||||
TileSheet &img,
|
||||
TileSheet::SubSheetIdx idx,
|
||||
Direction const dir) noexcept:
|
||||
m_img(img),
|
||||
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} {
|
||||
}
|
||||
|
||||
ox::Error RotateCommand::redo() noexcept {
|
||||
auto &ss = getSubSheet(m_img, m_idx);
|
||||
switch (m_dir) {
|
||||
case Direction::Left:
|
||||
rotateLeft(ss, m_pt1, m_pt2);
|
||||
break;
|
||||
case Direction::Right:
|
||||
rotateRight(ss, m_pt1, m_pt2);
|
||||
break;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Error RotateCommand::undo() noexcept {
|
||||
auto &ss = getSubSheet(m_img, m_idx);
|
||||
switch (m_dir) {
|
||||
case Direction::Left:
|
||||
rotateRight(ss, m_pt1, m_pt2);
|
||||
break;
|
||||
case Direction::Right:
|
||||
rotateLeft(ss, m_pt1, m_pt2);
|
||||
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,47 @@
|
||||
/*
|
||||
* 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;
|
||||
ox::Point const m_pt1;
|
||||
ox::Point const m_pt2;
|
||||
Direction const m_dir;
|
||||
|
||||
public:
|
||||
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 undo() noexcept final;
|
||||
|
||||
[[nodiscard]]
|
||||
int commandId() const noexcept final;
|
||||
|
||||
[[nodiscard]]
|
||||
TileSheet::SubSheetIdx const&subsheetIdx() const noexcept override;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -246,15 +246,31 @@ void TileSheetEditorImGui::draw(studio::StudioContext&) noexcept {
|
||||
//ig::ComboBox("##Operations", ox::Array<ox::CStringView, 1>{"Operations"}, i);
|
||||
}
|
||||
ImGui::EndChild();
|
||||
ImGui::BeginChild("OperationsBox", {0, 32}, true);
|
||||
ImGui::BeginChild("OperationsBox", {0, 35}, ImGuiWindowFlags_NoTitleBar);
|
||||
{
|
||||
auto constexpr btnSz = ImVec2{55, 16};
|
||||
if (ig::PushButton("Flip X", btnSz)) {
|
||||
oxLogError(m_model.flipX());
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ig::PushButton("Flip Y", btnSz)) {
|
||||
oxLogError(m_model.flipY());
|
||||
size_t i{};
|
||||
if (ig::ComboBox("##Operations", ox::SpanView<ox::CStringView>{{
|
||||
ox::CStringView{"Operations"},
|
||||
ox::CStringView{"Flip X"},
|
||||
ox::CStringView{"Flip Y"},
|
||||
ox::CStringView{"Rotate Left"},
|
||||
ox::CStringView{"Rotate Right"},
|
||||
}}, i)) {
|
||||
switch (i) {
|
||||
case 1:
|
||||
oxLogError(m_model.flipX());
|
||||
break;
|
||||
case 2:
|
||||
oxLogError(m_model.flipY());
|
||||
break;
|
||||
case 3:
|
||||
oxLogError(m_model.rotateLeft());
|
||||
break;
|
||||
case 4:
|
||||
oxLogError(m_model.rotateRight());
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "tilesheeteditormodel.hpp"
|
||||
|
||||
#include "commands/movesubsheetcommand.hpp"
|
||||
#include "commands/rotatecommand.hpp"
|
||||
|
||||
namespace nostalgia::gfx {
|
||||
|
||||
@@ -237,6 +238,28 @@ void TileSheetEditorModel::fill(ox::Point const&pt, int const palIdx) 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>(
|
||||
m_img, m_activeSubsSheetIdx, pt1, pt2, RotateCommand::Direction::Left));
|
||||
}
|
||||
|
||||
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>(
|
||||
m_img, m_activeSubsSheetIdx, pt1, pt2, RotateCommand::Direction::Right));
|
||||
}
|
||||
|
||||
void TileSheetEditorModel::setSelection(studio::Selection const&sel) noexcept {
|
||||
m_selection.emplace(sel);
|
||||
m_updated = true;
|
||||
|
||||
@@ -106,6 +106,10 @@ class TileSheetEditorModel: public ox::SignalHandler {
|
||||
|
||||
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 select(ox::Point const&pt) noexcept;
|
||||
|
||||
Reference in New Issue
Block a user