From 4ab710b155384fb55e0675e7832a225b0b0b5af5 Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Sat, 21 Oct 2023 01:18:46 -0500 Subject: [PATCH] [nostalgia/core] Move most TileSheet functions to cpp file --- .../core/include/nostalgia/core/tilesheet.hpp | 349 +++-------------- .../core/src/studio/tilesheeteditormodel.cpp | 16 +- .../core/src/studio/tilesheeteditormodel.hpp | 4 +- src/nostalgia/modules/core/src/tilesheet.cpp | 351 +++++++++++++++++- 4 files changed, 416 insertions(+), 304 deletions(-) diff --git a/src/nostalgia/modules/core/include/nostalgia/core/tilesheet.hpp b/src/nostalgia/modules/core/include/nostalgia/core/tilesheet.hpp index 832e8f39..e83fc528 100644 --- a/src/nostalgia/modules/core/include/nostalgia/core/tilesheet.hpp +++ b/src/nostalgia/modules/core/include/nostalgia/core/tilesheet.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -73,97 +74,39 @@ struct TileSheet { ox::Vector pixels; constexpr SubSheet() noexcept = default; - constexpr SubSheet(const SubSheet &other) noexcept { - id = other.id; - name = other.name; - columns = other.columns; - rows = other.rows; - subsheets = other.subsheets; - pixels = other.pixels; - } - constexpr SubSheet(SubSheet &&other) noexcept { - id = other.id; - name = std::move(other.name); - columns = other.columns; - rows = other.rows; - subsheets = std::move(other.subsheets); - pixels = std::move(other.pixels); - other.name = ""; - other.columns = 0; - other.rows = 0; - } - constexpr SubSheet( + constexpr SubSheet(SubSheet const&other) noexcept = default; + SubSheet(SubSheet &&other) noexcept; + SubSheet( SubSheetId pId, ox::CRStringView pName, int pColumns, int pRows, - int bpp) noexcept: - id(pId), name(pName), columns(pColumns), rows(pRows), - pixels(static_cast(columns * rows * PixelsPerTile) / (bpp == 4 ? 2u : 1u)) { - } - constexpr SubSheet( + int bpp) noexcept; + SubSheet( SubSheetId pId, ox::CRStringView pName, int pColumns, int pRows, - ox::Vector pPixels) noexcept: - id(pId), name(pName), columns(pColumns), rows(pRows), pixels(std::move(pPixels)) { - } + ox::Vector pPixels) noexcept; constexpr SubSheet &operator=(const SubSheet &other) noexcept = default; - constexpr SubSheet &operator=(SubSheet &&other) noexcept { - name = std::move(other.name); - columns = other.columns; - rows = other.rows; - subsheets = std::move(other.subsheets); - pixels = std::move(other.pixels); - return *this; - } + SubSheet &operator=(SubSheet &&other) noexcept; [[nodiscard]] - constexpr auto idx(const ox::Point &pt) const noexcept { - return ptToIdx(pt, columns); - } + std::size_t idx(const ox::Point &pt) const noexcept; /** * Reads all pixels of this sheet or its children into the given pixel list * @param pixels */ - constexpr void readPixelsTo(ox::Vector *pPixels, int8_t pBpp) const noexcept { - if (!subsheets.empty()) { - for (auto &s: subsheets) { - s.readPixelsTo(pPixels); - } - } else { - if (pBpp == 4) { - for (auto p: this->pixels) { - pPixels->emplace_back(static_cast(p & 0b1111)); - pPixels->emplace_back(static_cast(p >> 4)); - } - } else { - for (auto p: this->pixels) { - pPixels->emplace_back(p); - } - } - } - } + void readPixelsTo(ox::Vector *pPixels, int8_t pBpp) const noexcept; /** * Reads all pixels of this sheet or its children into the given pixel list * @param pixels */ - constexpr void readPixelsTo(ox::Vector *pPixels) const noexcept { - if (!subsheets.empty()) { - for (auto &s: subsheets) { - s.readPixelsTo(pPixels); - } - } else { - for (auto p : this->pixels) { - pPixels->emplace_back(p); - } - } - } + void readPixelsTo(ox::Vector *pPixels) const noexcept; [[nodiscard]] constexpr std::size_t size() const noexcept { @@ -171,54 +114,25 @@ struct TileSheet { } [[nodiscard]] - constexpr std::size_t unusedPixels() const noexcept { - std::size_t childrenSize = 0; - for (auto &c : subsheets) { - childrenSize += c.size(); - } - return size() - childrenSize; - } + std::size_t unusedPixels() const noexcept; [[nodiscard]] - constexpr uint8_t getPixel4Bpp(std::size_t idx) const noexcept { - if (idx & 1) { - return this->pixels[idx / 2] >> 4; - } else { - return this->pixels[idx / 2] & 0b0000'1111; - } - } + uint8_t getPixel4Bpp(std::size_t idx) const noexcept; [[nodiscard]] - constexpr uint8_t getPixel8Bpp(std::size_t idx) const noexcept { - return this->pixels[idx]; - } + uint8_t getPixel8Bpp(std::size_t idx) const noexcept; [[nodiscard]] - constexpr auto getPixel(int8_t pBpp, std::size_t idx) const noexcept { - if (pBpp == 4) { - return getPixel4Bpp(idx); - } else { - return getPixel8Bpp(idx); - } - } + uint8_t getPixel(int8_t pBpp, std::size_t idx) const noexcept; [[nodiscard]] - constexpr auto getPixel4Bpp(const ox::Point &pt) const noexcept { - const auto idx = ptToIdx(pt, columns); - return getPixel4Bpp(idx); - } + uint8_t getPixel4Bpp(const ox::Point &pt) const noexcept; [[nodiscard]] - constexpr auto getPixel8Bpp(const ox::Point &pt) const noexcept { - const auto idx = ptToIdx(pt, columns); - return getPixel8Bpp(idx); - } + uint8_t getPixel8Bpp(const ox::Point &pt) const noexcept; [[nodiscard]] - constexpr auto getPixel(int8_t pBpp, const ox::Point &pt) const noexcept { - const auto idx = ptToIdx(pt, columns); - return getPixel(pBpp, idx); - } + uint8_t getPixel(int8_t pBpp, const ox::Point &pt) const noexcept; constexpr auto walkPixels(int8_t pBpp, auto callback) const noexcept { if (pBpp == 4) { @@ -242,36 +156,11 @@ struct TileSheet { } } - constexpr void setPixel(int8_t pBpp, uint64_t idx, uint8_t palIdx) noexcept { - auto &pixel = this->pixels[static_cast(idx / 2)]; - if (pBpp == 4) { - if (idx & 1) { - pixel = static_cast((pixel & 0b0000'1111) | (palIdx << 4)); - } else { - pixel = (pixel & 0b1111'0000) | (palIdx); - } - } else { - pixel = palIdx; - } - } + void setPixel(int8_t pBpp, uint64_t idx, uint8_t palIdx) noexcept; - constexpr void setPixel(int8_t pBpp, const ox::Point &pt, uint8_t palIdx) noexcept { - const auto idx = ptToIdx(pt, columns); - setPixel(pBpp, idx, palIdx); - } + void setPixel(int8_t pBpp, const ox::Point &pt, uint8_t palIdx) noexcept; - constexpr auto setPixelCount(int8_t pBpp, std::size_t cnt) noexcept { - switch (pBpp) { - case 4: - pixels.resize(cnt / 2); - return OxError(0); - case 8: - pixels.resize(cnt); - return OxError(0); - default: - return OxError(1, "Invalid pBpp used for TileSheet::SubSheet::setPixelCount"); - } - } + ox::Error setPixelCount(int8_t pBpp, std::size_t cnt) noexcept; /** * Gets a count of the pixels in this sheet, and not that of its children. @@ -279,66 +168,25 @@ struct TileSheet { * @return a count of the pixels in this sheet */ [[nodiscard]] - constexpr unsigned pixelCnt(int8_t pBpp) const noexcept { - const auto pixelsSize = static_cast(pixels.size()); - return pBpp == 4 ? pixelsSize * 2 : pixelsSize; - } + unsigned pixelCnt(int8_t pBpp) const noexcept; /** * Gets the offset in tiles of the desired subsheet. */ [[nodiscard]] - constexpr ox::Result getTileOffset( - const auto &pNamePath, + ox::Result getTileOffset( + ox::SpanView const&pNamePath, int8_t pBpp, std::size_t pIt = 0, - unsigned pCurrentTotal = 0) const noexcept { - // pIt == pNamePath.size() - 1 && - if (name != pNamePath[pIt]) { - return OxError(2, "Wrong branch"); - } - if (pIt == pNamePath.size() - 1) { - return pCurrentTotal; - } - for (auto &sub : subsheets) { - auto [offset, err] = sub.getTileOffset( - pNamePath, pBpp, pIt + 1, pCurrentTotal); - if (!err) { - return offset; - } - pCurrentTotal += sub.pixelCnt(pBpp) / PixelsPerTile; - } - return OxError(1, "SubSheet not found"); - } + unsigned pCurrentTotal = 0) const noexcept; [[nodiscard]] - constexpr ox::Result getIdFor( - const auto &pNamePath, - std::size_t pIt = 0) const noexcept { - for (auto &sub : subsheets) { - if (sub.name == pNamePath[pIt]) { - if (pIt == pNamePath.size()) { - return id; - } - return getIdFor(pNamePath, pIt + 1); - } - } - return OxError(1, "SubSheet not found"); - } + ox::Result getIdFor( + ox::SpanView const&pNamePath, + std::size_t pIt = 0) const noexcept; [[nodiscard]] - constexpr ox::Result getNameFor(SubSheetId pId) const noexcept { - if (id == pId) { - return ox::StringView(name); - } - for (const auto &sub : subsheets) { - const auto [name, err] = sub.getNameFor(pId); - if (!err) { - return name; - } - } - return OxError(1, "SubSheet not found"); - } + ox::Result getNameFor(SubSheetId pId) const noexcept; }; @@ -358,43 +206,15 @@ struct TileSheet { subsheet(std::move(other.subsheet)) { } - inline auto &operator=(const TileSheet &other) noexcept { - if (this != &other) { - bpp = other.bpp; - idIt = other.idIt; - defaultPalette = other.defaultPalette; - subsheet = other.subsheet; - } - return *this; - } - inline auto &operator=(TileSheet &&other) noexcept { - bpp = other.bpp; - idIt = other.idIt; - defaultPalette = std::move(other.defaultPalette); - subsheet = std::move(other.subsheet); - return *this; - } + TileSheet &operator=(const TileSheet &other) noexcept; + + TileSheet &operator=(TileSheet &&other) noexcept; [[nodiscard]] - constexpr auto validateSubSheetIdx( + SubSheetIdx validateSubSheetIdx( const SubSheetIdx &pIdx, std::size_t pIdxIt, - const SubSheet *pSubsheet) noexcept { - if (pIdxIt == pIdx.size()) { - return pIdx; - } - const auto currentIdx = pIdx[pIdxIt]; - if (pSubsheet->subsheets.size() <= currentIdx) { - auto out = pIdx; - if (!pSubsheet->subsheets.empty()) { - *out.back().value = pSubsheet->subsheets.size() - 1; - } else { - out.pop_back(); - } - return out; - } - return validateSubSheetIdx(pIdx, pIdxIt + 1, &pSubsheet->subsheets[pIdx[pIdxIt]]); - } + const SubSheet *pSubsheet) noexcept; /** * validateSubSheetIdx takes a SubSheetIdx and moves the index to the @@ -404,112 +224,55 @@ struct TileSheet { * @return a valid version of idx */ [[nodiscard]] - constexpr auto validateSubSheetIdx(const SubSheetIdx &idx) noexcept { - return validateSubSheetIdx(idx, 0, &subsheet); - } + SubSheetIdx validateSubSheetIdx(const SubSheetIdx &idx) noexcept; [[nodiscard]] - constexpr static const SubSheet &getSubSheet( + static const SubSheet &getSubSheet( const SubSheetIdx &idx, std::size_t idxIt, - const SubSheet *pSubsheet) noexcept { - if (idxIt == idx.size()) { - return *pSubsheet; - } - const auto currentIdx = idx[idxIt]; - if (pSubsheet->subsheets.size() < currentIdx) { - return *pSubsheet; - } - return getSubSheet(idx, idxIt + 1, &pSubsheet->subsheets[currentIdx]); - } + const SubSheet *pSubsheet) noexcept; [[nodiscard]] - constexpr static SubSheet &getSubSheet( + static SubSheet &getSubSheet( const SubSheetIdx &idx, std::size_t idxIt, - SubSheet *pSubsheet) noexcept { - if (idxIt == idx.size()) { - return *pSubsheet; - } - return getSubSheet(idx, idxIt + 1, &pSubsheet->subsheets[idx[idxIt]]); - } + SubSheet *pSubsheet) noexcept; [[nodiscard]] - constexpr const SubSheet &getSubSheet(const SubSheetIdx &idx) const noexcept { - return getSubSheet(idx, 0, &subsheet); - } + const SubSheet &getSubSheet(const SubSheetIdx &idx) const noexcept; [[nodiscard]] - constexpr SubSheet &getSubSheet(const SubSheetIdx &idx) noexcept { - return getSubSheet(idx, 0, &subsheet); - } + SubSheet &getSubSheet(const SubSheetIdx &idx) noexcept; - constexpr ox::Error addSubSheet(const SubSheetIdx &idx) noexcept { - auto &parent = getSubSheet(idx); - if (parent.subsheets.size() < 2) { - parent.subsheets.emplace_back(idIt++, ox::sfmt("Subsheet {}", parent.subsheets.size()), 1, 1, bpp); - } else { - parent.subsheets.emplace_back(idIt++, "Subsheet 0", parent.columns, parent.rows, bpp); - parent.subsheets.emplace_back(idIt++, "Subsheet 1", 1, 1, bpp); - } - return OxError(0); - } + ox::Error addSubSheet(const SubSheetIdx &idx) noexcept; [[nodiscard]] - constexpr static auto rmSubSheet( + static ox::Error rmSubSheet( const SubSheetIdx &idx, std::size_t idxIt, - SubSheet *pSubsheet) noexcept { - if (idxIt == idx.size() - 1) { - return pSubsheet->subsheets.erase(idx[idxIt]).error; - } - return rmSubSheet(idx, idxIt + 1, &pSubsheet->subsheets[idx[idxIt]]); - } + SubSheet *pSubsheet) noexcept; [[nodiscard]] - constexpr auto rmSubSheet(const SubSheetIdx &idx) noexcept { - return rmSubSheet(idx, 0, &subsheet); - } + ox::Error rmSubSheet(const SubSheetIdx &idx) noexcept; [[nodiscard]] - constexpr auto getPixel4Bpp( + uint8_t getPixel4Bpp( const ox::Point &pt, - const SubSheetIdx &subsheetIdx) const noexcept { - oxAssert(bpp == 4, "TileSheet::getPixel4Bpp: wrong bpp"); - auto &s = this->getSubSheet(subsheetIdx); - const auto idx = ptToIdx(pt, s.columns); - return s.getPixel4Bpp(idx); - } + const SubSheetIdx &subsheetIdx) const noexcept; [[nodiscard]] - constexpr auto getPixel8Bpp( + uint8_t getPixel8Bpp( const ox::Point &pt, - const SubSheetIdx &subsheetIdx) const noexcept { - oxAssert(bpp == 8, "TileSheet::getPixel8Bpp: wrong bpp"); - auto &s = this->getSubSheet(subsheetIdx); - const auto idx = ptToIdx(pt, s.columns); - return s.getPixel8Bpp(idx); - } + const SubSheetIdx &subsheetIdx) const noexcept; + + ox::Result getIdFor(ox::CRStringView path) const noexcept; + + ox::Result getTileOffset(ox::CRStringView pNamePath) const noexcept; + + ox::Result getNameFor(SubSheetId pId) const noexcept; [[nodiscard]] - constexpr auto getIdFor(ox::CRStringView path) const noexcept { - return subsheet.getIdFor(ox::split<8>(path, '.')); - } - - constexpr ox::Result getTileOffset(const auto &pNamePath) const noexcept { - return subsheet.getTileOffset(ox::split<8>(pNamePath, '.'), bpp); - } - - constexpr ox::Result getNameFor(SubSheetId pId) const noexcept { - return subsheet.getNameFor(pId); - } - - [[nodiscard]] - auto pixels() const noexcept { - ox::Vector out; - subsheet.readPixelsTo(&out); - return out; - } + ox::Vector pixels() const noexcept; }; diff --git a/src/nostalgia/modules/core/src/studio/tilesheeteditormodel.cpp b/src/nostalgia/modules/core/src/studio/tilesheeteditormodel.cpp index a5967a11..d122b8af 100644 --- a/src/nostalgia/modules/core/src/studio/tilesheeteditormodel.cpp +++ b/src/nostalgia/modules/core/src/studio/tilesheeteditormodel.cpp @@ -103,7 +103,7 @@ class DrawCommand: public TileSheetCommand { int m_palIdx = 0; public: - constexpr DrawCommand( + DrawCommand( TileSheet &img, TileSheet::SubSheetIdx subSheetIdx, std::size_t idx, @@ -115,7 +115,7 @@ class DrawCommand: public TileSheetCommand { m_palIdx = palIdx; } - constexpr DrawCommand( + DrawCommand( TileSheet &img, TileSheet::SubSheetIdx subSheetIdx, const ox::Vector &idxList, @@ -129,7 +129,7 @@ class DrawCommand: public TileSheetCommand { m_palIdx = palIdx; } - constexpr auto append(std::size_t idx) noexcept { + auto append(std::size_t idx) noexcept { auto &subsheet = m_img.getSubSheet(m_subSheetIdx); if (m_changes.back().value->idx != idx && subsheet.getPixel(m_img.bpp, idx) != m_palIdx) { // duplicate entries are bad @@ -248,7 +248,7 @@ class AddSubSheetCommand: public TileSheetCommand { ox::Vector m_addedSheets; public: - constexpr AddSubSheetCommand(TileSheet &img, TileSheet::SubSheetIdx parentIdx) noexcept: + AddSubSheetCommand(TileSheet &img, TileSheet::SubSheetIdx parentIdx) noexcept: m_img(img), m_parentIdx(std::move(parentIdx)) { auto &parent = m_img.getSubSheet(m_parentIdx); @@ -313,7 +313,7 @@ class RmSubSheetCommand: public TileSheetCommand { TileSheet::SubSheet m_sheet; public: - constexpr RmSubSheetCommand(TileSheet &img, TileSheet::SubSheetIdx idx) noexcept: + RmSubSheetCommand(TileSheet &img, TileSheet::SubSheetIdx idx) noexcept: m_img(img), m_idx(std::move(idx)) { m_parentIdx = idx; @@ -354,7 +354,7 @@ class InsertTilesCommand: public TileSheetCommand { ox::Vector m_deletedPixels = {}; public: - constexpr InsertTilesCommand( + InsertTilesCommand( TileSheet &img, TileSheet::SubSheetIdx idx, std::size_t tileIdx, @@ -419,7 +419,7 @@ class DeleteTilesCommand: public TileSheetCommand { ox::Vector m_deletedPixels = {}; public: - constexpr DeleteTilesCommand( + DeleteTilesCommand( TileSheet &img, TileSheet::SubSheetIdx idx, std::size_t tileIdx, @@ -485,7 +485,7 @@ class UpdateSubSheetCommand: public TileSheetCommand { int m_newRows = 0; public: - constexpr UpdateSubSheetCommand( + UpdateSubSheetCommand( TileSheet &img, TileSheet::SubSheetIdx idx, const ox::String &name, diff --git a/src/nostalgia/modules/core/src/studio/tilesheeteditormodel.hpp b/src/nostalgia/modules/core/src/studio/tilesheeteditormodel.hpp index 1f6eb87b..a79a91f5 100644 --- a/src/nostalgia/modules/core/src/studio/tilesheeteditormodel.hpp +++ b/src/nostalgia/modules/core/src/studio/tilesheeteditormodel.hpp @@ -76,13 +76,13 @@ class TileSheetEditorModel: public ox::SignalHandler { void setActiveSubsheet(const TileSheet::SubSheetIdx&) noexcept; [[nodiscard]] - constexpr const TileSheet::SubSheet *activeSubSheet() const noexcept { + const TileSheet::SubSheet *activeSubSheet() const noexcept { auto &activeSubSheet = m_img.getSubSheet(m_activeSubsSheetIdx); return &activeSubSheet; } [[nodiscard]] - constexpr TileSheet::SubSheet *activeSubSheet() noexcept { + TileSheet::SubSheet *activeSubSheet() noexcept { auto &activeSubSheet = m_img.getSubSheet(m_activeSubsSheetIdx); return &activeSubSheet; } diff --git a/src/nostalgia/modules/core/src/tilesheet.cpp b/src/nostalgia/modules/core/src/tilesheet.cpp index ed8e3c28..c40a8267 100644 --- a/src/nostalgia/modules/core/src/tilesheet.cpp +++ b/src/nostalgia/modules/core/src/tilesheet.cpp @@ -6,13 +6,362 @@ #include #include +#include namespace nostalgia::core { +TileSheet::SubSheet::SubSheet(SubSheet &&other) noexcept: + id (other.id), + name (std::move(other.name)), + columns (other.columns), + rows (other.rows), + subsheets(std::move(other.subsheets)), + pixels (std::move(other.pixels)) { + other.name = ""; + other.columns = {}; + other.rows = {}; +} + +TileSheet::SubSheet::SubSheet( + SubSheetId pId, + ox::CRStringView pName, + int pColumns, + int pRows, + int bpp) noexcept: + id(pId), + name(pName), + columns(pColumns), + rows(pRows), + pixels(static_cast(columns * rows * PixelsPerTile) / (bpp == 4 ? 2u : 1u)) { +} + +TileSheet::SubSheet::SubSheet( + SubSheetId pId, + ox::CRStringView pName, + int pColumns, + int pRows, + ox::Vector pPixels) noexcept: + id(pId), + name(pName), + columns(pColumns), + rows(pRows), + pixels(std::move(pPixels)) { +} + +TileSheet::SubSheet &TileSheet::SubSheet::operator=(TileSheet::SubSheet &&other) noexcept { + name = std::move(other.name); + columns = other.columns; + rows = other.rows; + subsheets = std::move(other.subsheets); + pixels = std::move(other.pixels); + return *this; +} + +std::size_t TileSheet::SubSheet::idx(const ox::Point &pt) const noexcept { + return ptToIdx(pt, columns); +} + +void TileSheet::SubSheet::readPixelsTo(ox::Vector *pPixels, int8_t pBpp) const noexcept { + if (!subsheets.empty()) { + for (auto &s: subsheets) { + s.readPixelsTo(pPixels); + } + } else { + if (pBpp == 4) { + for (auto p: this->pixels) { + pPixels->emplace_back(static_cast(p & 0b1111)); + pPixels->emplace_back(static_cast(p >> 4)); + } + } else { + for (auto p: this->pixels) { + pPixels->emplace_back(p); + } + } + } +} + +void TileSheet::SubSheet::readPixelsTo(ox::Vector *pPixels) const noexcept { + if (!subsheets.empty()) { + for (auto &s: subsheets) { + s.readPixelsTo(pPixels); + } + } else { + for (auto p : this->pixels) { + pPixels->emplace_back(p); + } + } +} + +std::size_t TileSheet::SubSheet::unusedPixels() const noexcept { + std::size_t childrenSize = 0; + for (auto &c : subsheets) { + childrenSize += c.size(); + } + return size() - childrenSize; +} + +uint8_t TileSheet::SubSheet::getPixel4Bpp(std::size_t idx) const noexcept { + if (idx & 1) { + return this->pixels[idx / 2] >> 4; + } else { + return this->pixels[idx / 2] & 0b0000'1111; + } +} + +uint8_t TileSheet::SubSheet::getPixel8Bpp(std::size_t idx) const noexcept { + return this->pixels[idx]; +} + +uint8_t TileSheet::SubSheet::getPixel(int8_t pBpp, std::size_t idx) const noexcept { + if (pBpp == 4) { + return getPixel4Bpp(idx); + } else { + return getPixel8Bpp(idx); + } +} + +uint8_t TileSheet::SubSheet::getPixel4Bpp(const ox::Point &pt) const noexcept { + const auto idx = ptToIdx(pt, columns); + return getPixel4Bpp(idx); +} + +uint8_t TileSheet::SubSheet::getPixel8Bpp(const ox::Point &pt) const noexcept { + const auto idx = ptToIdx(pt, columns); + return getPixel8Bpp(idx); +} + +uint8_t TileSheet::SubSheet::getPixel(int8_t pBpp, const ox::Point &pt) const noexcept { + const auto idx = ptToIdx(pt, columns); + return getPixel(pBpp, idx); +} + +void TileSheet::SubSheet::setPixel(int8_t pBpp, uint64_t idx, uint8_t palIdx) noexcept { + auto &pixel = this->pixels[static_cast(idx / 2)]; + if (pBpp == 4) { + if (idx & 1) { + pixel = static_cast((pixel & 0b0000'1111) | (palIdx << 4)); + } else { + pixel = (pixel & 0b1111'0000) | (palIdx); + } + } else { + pixel = palIdx; + } +} + +void TileSheet::SubSheet::setPixel(int8_t pBpp, const ox::Point &pt, uint8_t palIdx) noexcept { + const auto idx = ptToIdx(pt, columns); + setPixel(pBpp, idx, palIdx); +} + +ox::Error TileSheet::SubSheet::setPixelCount(int8_t pBpp, std::size_t cnt) noexcept { + switch (pBpp) { + case 4: + pixels.resize(cnt / 2); + return OxError(0); + case 8: + pixels.resize(cnt); + return OxError(0); + default: + return OxError(1, "Invalid pBpp used for TileSheet::SubSheet::setPixelCount"); + } +} + +unsigned TileSheet::SubSheet::pixelCnt(int8_t pBpp) const noexcept { + const auto pixelsSize = static_cast(pixels.size()); + return pBpp == 4 ? pixelsSize * 2 : pixelsSize; +} + +ox::Result TileSheet::SubSheet::getTileOffset( + ox::SpanView const&pNamePath, + int8_t pBpp, + std::size_t pIt, + unsigned pCurrentTotal) const noexcept { + // pIt == pNamePath.size() - 1 && + if (name != pNamePath[pIt]) { + return OxError(2, "Wrong branch"); + } + if (pIt == pNamePath.size() - 1) { + return pCurrentTotal; + } + for (auto &sub : subsheets) { + auto [offset, err] = sub.getTileOffset( + pNamePath, pBpp, pIt + 1, pCurrentTotal); + if (!err) { + return offset; + } + pCurrentTotal += sub.pixelCnt(pBpp) / PixelsPerTile; + } + return OxError(1, "SubSheet not found"); +} + +ox::Result TileSheet::SubSheet::getIdFor( + ox::SpanView const&pNamePath, + std::size_t pIt) const noexcept { + for (auto &sub : subsheets) { + if (sub.name == pNamePath[pIt]) { + if (pIt == pNamePath.size()) { + return id; + } + return getIdFor(pNamePath, pIt + 1); + } + } + return OxError(1, "SubSheet not found"); +} + +ox::Result TileSheet::SubSheet::getNameFor(SubSheetId pId) const noexcept { + if (id == pId) { + return ox::StringView(name); + } + for (const auto &sub : subsheets) { + const auto [name, err] = sub.getNameFor(pId); + if (!err) { + return name; + } + } + return OxError(1, "SubSheet not found"); +} + + +TileSheet &TileSheet::operator=(const TileSheet &other) noexcept { + if (this != &other) { + bpp = other.bpp; + idIt = other.idIt; + defaultPalette = other.defaultPalette; + subsheet = other.subsheet; + } + return *this; +} + +TileSheet &TileSheet::operator=(TileSheet &&other) noexcept { + bpp = other.bpp; + idIt = other.idIt; + defaultPalette = std::move(other.defaultPalette); + subsheet = std::move(other.subsheet); + return *this; +} + +TileSheet::SubSheetIdx TileSheet::validateSubSheetIdx( + const SubSheetIdx &pIdx, + std::size_t pIdxIt, + const SubSheet *pSubsheet) noexcept { + if (pIdxIt == pIdx.size()) { + return pIdx; + } + const auto currentIdx = pIdx[pIdxIt]; + if (pSubsheet->subsheets.size() <= currentIdx) { + auto out = pIdx; + if (!pSubsheet->subsheets.empty()) { + *out.back().value = pSubsheet->subsheets.size() - 1; + } else { + out.pop_back(); + } + return out; + } + return validateSubSheetIdx(pIdx, pIdxIt + 1, &pSubsheet->subsheets[pIdx[pIdxIt]]); +} + +TileSheet::SubSheetIdx TileSheet::validateSubSheetIdx(const SubSheetIdx &idx) noexcept { + return validateSubSheetIdx(idx, 0, &subsheet); +} + +const TileSheet::SubSheet &TileSheet::getSubSheet( + const TileSheet::SubSheetIdx &idx, + std::size_t idxIt, + const SubSheet *pSubsheet) noexcept { + if (idxIt == idx.size()) { + return *pSubsheet; + } + const auto currentIdx = idx[idxIt]; + if (pSubsheet->subsheets.size() < currentIdx) { + return *pSubsheet; + } + return getSubSheet(idx, idxIt + 1, &pSubsheet->subsheets[currentIdx]); +} + +TileSheet::SubSheet &TileSheet::getSubSheet( + const TileSheet::SubSheetIdx &idx, + std::size_t idxIt, + TileSheet::SubSheet *pSubsheet) noexcept { + if (idxIt == idx.size()) { + return *pSubsheet; + } + return getSubSheet(idx, idxIt + 1, &pSubsheet->subsheets[idx[idxIt]]); +} + +const TileSheet::SubSheet &TileSheet::getSubSheet(const TileSheet::SubSheetIdx &idx) const noexcept { + return getSubSheet(idx, 0, &subsheet); +} + +TileSheet::SubSheet &TileSheet::getSubSheet(const TileSheet::SubSheetIdx &idx) noexcept { + return getSubSheet(idx, 0, &subsheet); +} + +ox::Error TileSheet::addSubSheet(const TileSheet::SubSheetIdx &idx) noexcept { + auto &parent = getSubSheet(idx); + if (parent.subsheets.size() < 2) { + parent.subsheets.emplace_back(idIt++, ox::sfmt("Subsheet {}", parent.subsheets.size()), 1, 1, bpp); + } else { + parent.subsheets.emplace_back(idIt++, "Subsheet 0", parent.columns, parent.rows, bpp); + parent.subsheets.emplace_back(idIt++, "Subsheet 1", 1, 1, bpp); + } + return OxError(0); +} + +ox::Error TileSheet::rmSubSheet( + const SubSheetIdx &idx, + std::size_t idxIt, + SubSheet *pSubsheet) noexcept { + if (idxIt == idx.size() - 1) { + return pSubsheet->subsheets.erase(idx[idxIt]).error; + } + return rmSubSheet(idx, idxIt + 1, &pSubsheet->subsheets[idx[idxIt]]); +} + +ox::Error TileSheet::rmSubSheet(const TileSheet::SubSheetIdx &idx) noexcept { + return rmSubSheet(idx, 0, &subsheet); +} + +uint8_t TileSheet::getPixel4Bpp( + const ox::Point &pt, + const TileSheet::SubSheetIdx &subsheetIdx) const noexcept { + oxAssert(bpp == 4, "TileSheet::getPixel4Bpp: wrong bpp"); + auto &s = this->getSubSheet(subsheetIdx); + const auto idx = ptToIdx(pt, s.columns); + return s.getPixel4Bpp(idx); +} + +uint8_t TileSheet::getPixel8Bpp( + const ox::Point &pt, + const TileSheet::SubSheetIdx &subsheetIdx) const noexcept { + oxAssert(bpp == 8, "TileSheet::getPixel8Bpp: wrong bpp"); + auto &s = this->getSubSheet(subsheetIdx); + const auto idx = ptToIdx(pt, s.columns); + return s.getPixel8Bpp(idx); +} + +ox::Result TileSheet::getIdFor(ox::CRStringView path) const noexcept { + return subsheet.getIdFor(ox::split<8>(path, '.')); +} + +ox::Result TileSheet::getTileOffset(ox::CRStringView pNamePath) const noexcept { + return subsheet.getTileOffset(ox::split<8>(pNamePath, '.'), bpp); +} + +ox::Result TileSheet::getNameFor(SubSheetId pId) const noexcept { + return subsheet.getNameFor(pId); +} + +ox::Vector TileSheet::pixels() const noexcept { + ox::Vector out; + subsheet.readPixelsTo(&out); + return out; +} + + ox::Vector resizeTileSheetData( ox::Vector const&srcPixels, ox::Size const&srcSize, - int scale = 2) noexcept { + int scale) noexcept { ox::Vector dst; auto dstWidth = srcSize.width * scale; auto dstHeight = srcSize.height * scale;