From 37e65ab0a67afcff808037f561e80b3dcb991982 Mon Sep 17 00:00:00 2001
From: Gary Talent <gary@drinkingtea.net>
Date: Thu, 23 May 2024 20:52:55 -0500
Subject: [PATCH] [nostalgia/core/studio] Fix Subsheet width to update properly

---
 .../core/include/nostalgia/core/tilesheet.hpp |  8 ++
 .../commands/updatesubsheetcommand.cpp        |  4 +-
 src/nostalgia/modules/core/src/tilesheet.cpp  | 74 +++++++++++++------
 3 files changed, 61 insertions(+), 25 deletions(-)

diff --git a/src/nostalgia/modules/core/include/nostalgia/core/tilesheet.hpp b/src/nostalgia/modules/core/include/nostalgia/core/tilesheet.hpp
index 7a673d83..5aa926b5 100644
--- a/src/nostalgia/modules/core/include/nostalgia/core/tilesheet.hpp
+++ b/src/nostalgia/modules/core/include/nostalgia/core/tilesheet.hpp
@@ -222,6 +222,14 @@ ox::Error setPixelCount(TileSheet::SubSheet &ss, int8_t pBpp, std::size_t cnt) n
 [[nodiscard]]
 unsigned pixelCnt(TileSheet::SubSheet const&ss, int8_t pBpp) noexcept;
 
+/**
+ *
+ * @param ss
+ * @param pBpp
+ * @param sz size of Subsheet in tiles (not pixels)
+ */
+ox::Error resizeSubsheet(TileSheet::SubSheet &ss, int8_t pBpp, ox::Size const&sz) noexcept;
+
 /**
  * validateSubSheetIdx takes a SubSheetIdx and moves the index to the
  * preceding or parent sheet if the current corresponding sheet does
diff --git a/src/nostalgia/modules/core/src/studio/tilesheeteditor/commands/updatesubsheetcommand.cpp b/src/nostalgia/modules/core/src/studio/tilesheeteditor/commands/updatesubsheetcommand.cpp
index 2083653c..4833e6fc 100644
--- a/src/nostalgia/modules/core/src/studio/tilesheeteditor/commands/updatesubsheetcommand.cpp
+++ b/src/nostalgia/modules/core/src/studio/tilesheeteditor/commands/updatesubsheetcommand.cpp
@@ -23,9 +23,7 @@ core::UpdateSubSheetCommand::UpdateSubSheetCommand(
 void UpdateSubSheetCommand::redo() noexcept {
 	auto &sheet = getSubSheet(m_img, m_idx);
 	sheet.name = m_newName;
-	sheet.columns = m_newCols;
-	sheet.rows = m_newRows;
-	oxLogError(setPixelCount(sheet, m_img.bpp, static_cast<std::size_t>(PixelsPerTile * m_newCols * m_newRows)));
+	oxLogError(resizeSubsheet(sheet, m_img.bpp, {m_newCols, m_newRows}));
 }
 
 void UpdateSubSheetCommand::undo() noexcept {
diff --git a/src/nostalgia/modules/core/src/tilesheet.cpp b/src/nostalgia/modules/core/src/tilesheet.cpp
index 58ebc156..cdd67ae1 100644
--- a/src/nostalgia/modules/core/src/tilesheet.cpp
+++ b/src/nostalgia/modules/core/src/tilesheet.cpp
@@ -10,16 +10,16 @@
 
 namespace nostalgia::core {
 
-std::size_t idx(TileSheet::SubSheet const&ss, ox::Point const&pt) noexcept {
+std::size_t idx(TileSheet::SubSheet const &ss, ox::Point const &pt) noexcept {
 	return ptToIdx(pt, ss.columns);
 }
 
 [[nodiscard]]
-static TileSheet::SubSheet const*getSubsheet(TileSheet::SubSheet const&ss, SubSheetId const id) noexcept {
+static TileSheet::SubSheet const *getSubsheet(TileSheet::SubSheet const &ss, SubSheetId const id) noexcept {
 	if (ss.id == id) {
 		return &ss;
 	}
-	for (auto const&child : ss.subsheets) {
+	for (auto const &child: ss.subsheets) {
 		if (auto out = getSubsheet(child, id)) {
 			return out;
 		}
@@ -28,33 +28,33 @@ static TileSheet::SubSheet const*getSubsheet(TileSheet::SubSheet const&ss, SubSh
 }
 
 [[nodiscard]]
-static size_t getTileCnt(TileSheet::SubSheet const&ss, int const bpp) noexcept {
+static size_t getTileCnt(TileSheet::SubSheet const &ss, int const bpp) noexcept {
 	if (ss.subsheets.empty()) {
 		auto const bytesPerTile = bpp == 4 ? 32u : 64u;
 		return ss.pixels.size() / bytesPerTile;
 	} else {
 		size_t out{};
-		for (auto const&child : ss.subsheets) {
+		for (auto const &child: ss.subsheets) {
 			out += getTileCnt(child, bpp);
 		}
 		return out;
 	}
 }
 
-size_t getTileCnt(TileSheet const&ts) noexcept {
+size_t getTileCnt(TileSheet const &ts) noexcept {
 	return getTileCnt(ts.subsheet, ts.bpp);
 }
 
-TileSheet::SubSheet const*getSubsheet(TileSheet const&ts, SubSheetId const id) noexcept {
+TileSheet::SubSheet const *getSubsheet(TileSheet const &ts, SubSheetId const id) noexcept {
 	return getSubsheet(ts.subsheet, id);
 }
 
 static ox::Optional<size_t> getPixelIdx(
-		TileSheet::SubSheet const&ss,
+		TileSheet::SubSheet const &ss,
 		SubSheetId const id,
 		size_t idx,
 		int8_t const bpp) noexcept {
-	for (auto const&child : ss.subsheets) {
+	for (auto const &child: ss.subsheets) {
 		if (child.id == id) {
 			return ox::Optional<size_t>(ox::in_place, idx);
 		}
@@ -66,12 +66,12 @@ static ox::Optional<size_t> getPixelIdx(
 	return {};
 }
 
-size_t getTileIdx(TileSheet const&ts, SubSheetId const id) noexcept {
+size_t getTileIdx(TileSheet const &ts, SubSheetId const id) noexcept {
 	auto const out = getPixelIdx(ts.subsheet, id, 0, ts.bpp);
 	return out.or_value(0) / PixelsPerTile;
 }
 
-uint8_t getPixel4Bpp(TileSheet::SubSheet const&ss, std::size_t idx) noexcept {
+uint8_t getPixel4Bpp(TileSheet::SubSheet const &ss, std::size_t idx) noexcept {
 	if (idx & 1) {
 		return ss.pixels[idx / 2] >> 4;
 	} else {
@@ -79,11 +79,11 @@ uint8_t getPixel4Bpp(TileSheet::SubSheet const&ss, std::size_t idx) noexcept {
 	}
 }
 
-uint8_t getPixel8Bpp(TileSheet::SubSheet const&ss, std::size_t idx) noexcept {
+uint8_t getPixel8Bpp(TileSheet::SubSheet const &ss, std::size_t idx) noexcept {
 	return ss.pixels[idx];
 }
 
-uint8_t getPixel(TileSheet::SubSheet const&ss, int8_t pBpp, std::size_t idx) noexcept {
+uint8_t getPixel(TileSheet::SubSheet const &ss, int8_t pBpp, std::size_t idx) noexcept {
 	if (pBpp == 4) {
 		return getPixel4Bpp(ss, idx);
 	} else {
@@ -91,23 +91,23 @@ uint8_t getPixel(TileSheet::SubSheet const&ss, int8_t pBpp, std::size_t idx) noe
 	}
 }
 
-uint8_t getPixel4Bpp(TileSheet::SubSheet const&ss, ox::Point const&pt) noexcept {
+uint8_t getPixel4Bpp(TileSheet::SubSheet const &ss, ox::Point const &pt) noexcept {
 	const auto idx = ptToIdx(pt, ss.columns);
 	return getPixel4Bpp(ss, idx);
 }
 
-uint8_t getPixel8Bpp(TileSheet::SubSheet const&ss, ox::Point const&pt) noexcept {
+uint8_t getPixel8Bpp(TileSheet::SubSheet const &ss, ox::Point const &pt) noexcept {
 	const auto idx = ptToIdx(pt, ss.columns);
 	return getPixel8Bpp(ss, idx);
 }
 
-uint8_t getPixel(TileSheet::SubSheet const&ss, int8_t pBpp, ox::Point const&pt) noexcept {
+uint8_t getPixel(TileSheet::SubSheet const &ss, int8_t pBpp, ox::Point const &pt) noexcept {
 	const auto idx = ptToIdx(pt, ss.columns);
 	return getPixel(ss, pBpp, idx);
 }
 
-void setPixel(TileSheet::SubSheet &ss, int8_t pBpp, uint64_t idx, uint8_t palIdx) noexcept {
-	auto &pixel = ss.pixels[static_cast<std::size_t>(idx / 2)];
+static void setPixel(ox::Vector<uint8_t> &pixels, int8_t pBpp, uint64_t idx, uint8_t palIdx) noexcept {
+	auto &pixel = pixels[static_cast<std::size_t>(idx / 2)];
 	if (pBpp == 4) {
 		if (idx & 1) {
 			pixel = static_cast<uint8_t>((pixel & 0b0000'1111) | (palIdx << 4));
@@ -119,29 +119,59 @@ void setPixel(TileSheet::SubSheet &ss, int8_t pBpp, uint64_t idx, uint8_t palIdx
 	}
 }
 
-void setPixel(TileSheet::SubSheet &ss, int8_t pBpp, ox::Point const&pt, uint8_t palIdx) noexcept {
+void setPixel(TileSheet::SubSheet &ss, int8_t pBpp, uint64_t idx, uint8_t palIdx) noexcept {
+	setPixel(ss.pixels, pBpp, idx, palIdx);
+}
+
+static void setPixel(ox::Vector<uint8_t> &pixels, int columns, int8_t pBpp, ox::Point const &pt, uint8_t palIdx) noexcept {
+	const auto idx = ptToIdx(pt, columns);
+	setPixel(pixels, pBpp, idx, palIdx);
+}
+
+void setPixel(TileSheet::SubSheet &ss, int8_t pBpp, ox::Point const &pt, uint8_t palIdx) noexcept {
 	const auto idx = ptToIdx(pt, ss.columns);
 	setPixel(ss, pBpp, idx, palIdx);
 }
 
-ox::Error setPixelCount(TileSheet::SubSheet &ss, int8_t pBpp, std::size_t cnt) noexcept {
+static ox::Error setPixelCount(ox::Vector<uint8_t> &pixels, int8_t pBpp, std::size_t cnt) noexcept {
 	switch (pBpp) {
 		case 4:
-			ss.pixels.resize(cnt / 2);
+			pixels.resize(cnt / 2);
 			return OxError(0);
 		case 8:
-			ss.pixels.resize(cnt);
+			pixels.resize(cnt);
 			return OxError(0);
 		default:
 			return OxError(1, "Invalid pBpp used for TileSheet::SubSheet::setPixelCount");
 	}
 }
 
+ox::Error setPixelCount(TileSheet::SubSheet &ss, int8_t pBpp, std::size_t cnt) noexcept {
+	return setPixelCount(ss.pixels, pBpp, cnt);
+}
+
 unsigned pixelCnt(TileSheet::SubSheet const&ss, int8_t pBpp) noexcept {
 	const auto pixelsSize = static_cast<unsigned>(ss.pixels.size());
 	return pBpp == 4 ? pixelsSize * 2 : pixelsSize;
 }
 
+ox::Error resizeSubsheet(TileSheet::SubSheet &ss, int8_t pBpp, ox::Size const &sz) noexcept {
+	ox::Vector<uint8_t> out;
+	oxReturnError(setPixelCount(out, pBpp, static_cast<size_t>(sz.width * sz.height) * PixelsPerTile));
+	auto const w = sz.width * TileWidth;
+	auto const h = sz.height * TileHeight;
+	for (auto x = 0; x < w; ++x) {
+		for (auto y = 0; y < h; ++y) {
+			auto const palIdx = getPixel(ss, pBpp, {x, y});
+			setPixel(out, sz.width, pBpp, {x, y}, palIdx);
+		}
+	}
+	ss.columns = sz.width;
+	ss.rows = sz.height;
+	ss.pixels = std::move(out);
+	return {};
+}
+
 ox::Result<ox::StringView> getNameFor(TileSheet::SubSheet const&ss, SubSheetId pId) noexcept {
 	if (ss.id == pId) {
 		return ox::StringView(ss.name);