From f987b02c657802c25061e6786fc28c562877c9c6 Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Tue, 21 Jan 2025 02:21:01 -0600 Subject: [PATCH] [nostalgia/gfx] Move to TileSheetV5 --- .../gfx/include/nostalgia/gfx/tilesheet.hpp | 156 ++++++++++++---- .../modules/gfx/src/keel/keelmodule.cpp | 3 + .../modules/gfx/src/keel/typeconv.cpp | 40 +++++ .../modules/gfx/src/keel/typeconv.hpp | 9 + .../commands/addsubsheetcommand.cpp | 4 +- .../commands/cutpastecommand.cpp | 6 +- .../tilesheeteditor/commands/drawcommand.cpp | 14 +- .../commands/updatesubsheetcommand.cpp | 2 +- .../tilesheeteditor/tilesheeteditormodel.cpp | 12 +- .../tilesheeteditor/tilesheetpixels.cpp | 1 + src/nostalgia/modules/gfx/src/tilesheet.cpp | 170 +++++++----------- 11 files changed, 264 insertions(+), 153 deletions(-) diff --git a/src/nostalgia/modules/gfx/include/nostalgia/gfx/tilesheet.hpp b/src/nostalgia/modules/gfx/include/nostalgia/gfx/tilesheet.hpp index ac1cd5b8..d2e5a575 100644 --- a/src/nostalgia/modules/gfx/include/nostalgia/gfx/tilesheet.hpp +++ b/src/nostalgia/modules/gfx/include/nostalgia/gfx/tilesheet.hpp @@ -5,10 +5,8 @@ #pragma once #include -#include #include #include -#include #include #include @@ -290,7 +288,105 @@ constexpr ox::Error repair(TileSheetV4 &ts) noexcept { } -using TileSheet = TileSheetV4; +struct TileSheetV5 { + using SubSheetIdx = ox::Vector; + + struct SubSheet { + static constexpr auto TypeName = "net.drinkingtea.nostalgia.gfx.TileSheet.SubSheet"; + static constexpr auto TypeVersion = 5; + SubSheetId id = 0; + ox::String name; + int columns = 0; + int rows = 0; + ox::Vector subsheets; + ox::Vector pixels; + + constexpr SubSheet() noexcept = default; + SubSheet( + SubSheetId const pId, + ox::StringParam pName, + int const pColumns, + int const pRows) noexcept: + id(pId), + name(std::move(pName)), + columns(pColumns), + rows(pRows), + pixels(static_cast(columns * rows * PixelsPerTile)) { + } + SubSheet( + SubSheetId const pId, + ox::StringParam pName, + int const pColumns, + int const pRows, + ox::Vector pPixels) noexcept: + id(pId), + name(std::move(pName)), + columns(pColumns), + rows(pRows), + pixels(std::move(pPixels)) { + } + + /** + * + * @return the dimensional size of the SubSheet (e.g. width * height) + */ + [[nodiscard]] + constexpr std::size_t size() const noexcept { + return static_cast(columns) * static_cast(rows); + } + + }; + + static constexpr auto TypeName = "net.drinkingtea.nostalgia.gfx.TileSheet"; + static constexpr auto TypeVersion = 5; + int8_t bpp = 4; + SubSheetId idIt = 0; + ox::FileAddress defaultPalette; + SubSheet subsheet{0, "Root", 1, 1}; + +}; + +[[nodiscard]] +constexpr bool valid(TileSheetV5::SubSheet const&ss) noexcept { + if (ss.subsheets.empty()) { + return static_cast(ss.columns * ss.rows * PixelsPerTile) == ss.pixels.size(); + } else { + return ss.pixels.empty() && ox::all_of(ss.subsheets.begin(), ss.subsheets.end(), + [](TileSheetV5::SubSheet const&s) { + return valid(s); + }); + } +} + +[[nodiscard]] +constexpr bool valid(TileSheetV5 const&ts) noexcept { + return (ts.bpp == 4 || ts.bpp == 8) && valid(ts.subsheet); +} + +constexpr void repair(TileSheetV5::SubSheet &ss, int const bpp) noexcept { + if (ss.subsheets.empty()) { + auto const bytes = static_cast(ss.columns * ss.rows * PixelsPerTile); + ss.pixels.resize(bytes); + } else { + ss.pixels.clear(); + ss.columns = -1; + ss.rows = -1; + } + for (auto &s : ss.subsheets) { + repair(s, bpp); + } +} + +constexpr ox::Error repair(TileSheetV5 &ts) noexcept { + if (ts.bpp != 4 && ts.bpp != 8) { + return ox::Error{1, "Unable to repair TileSheet"}; + } + repair(ts.subsheet, ts.bpp); + return {}; +} + + +using TileSheet = TileSheetV5; [[nodiscard]] std::size_t idx(TileSheet::SubSheet const&ss, ox::Point const&pt) noexcept; @@ -311,7 +407,7 @@ uint8_t getPixel4Bpp(TileSheet::SubSheet const&ss, std::size_t idx) noexcept; uint8_t getPixel8Bpp(TileSheet::SubSheet const&ss, std::size_t idx) noexcept; [[nodiscard]] -uint8_t getPixel(TileSheet::SubSheet const&ss, int8_t pBpp, std::size_t idx) noexcept; +uint8_t getPixel(TileSheet::SubSheet const&ss, std::size_t idx) noexcept; [[nodiscard]] uint8_t getPixel4Bpp(TileSheet::SubSheet const&ss, ox::Point const&pt) noexcept; @@ -320,44 +416,24 @@ uint8_t getPixel4Bpp(TileSheet::SubSheet const&ss, ox::Point const&pt) noexcept; uint8_t getPixel8Bpp(TileSheet::SubSheet const&ss, ox::Point const&pt) noexcept; [[nodiscard]] -uint8_t getPixel(TileSheet::SubSheet const&ss, int8_t pBpp, ox::Point const&pt) noexcept; +uint8_t getPixel(TileSheet::SubSheet const&ss, ox::Point const&pt) noexcept; -constexpr void walkPixels(TileSheet::SubSheet const&ss, int8_t pBpp, auto callback) noexcept { - if (pBpp == 4) { - const auto pixelCnt = ox::min( - static_cast(ss.columns * ss.rows * PixelsPerTile) / 2, - ss.pixels.size()); - //oxAssert(pixels.size() == pixelCnt, "Pixel count does not match rows and columns"); - for (std::size_t i = 0; i < pixelCnt; ++i) { - const auto colorIdx1 = static_cast(ss.pixels[i] & 0xF); - const auto colorIdx2 = static_cast(ss.pixels[i] >> 4); - callback(i * 2 + 0, colorIdx1); - callback(i * 2 + 1, colorIdx2); - } - } else { - const auto pixelCnt = ox::min( - static_cast(ss.columns * ss.rows * PixelsPerTile), - ss.pixels.size()); - for (std::size_t i = 0; i < pixelCnt; ++i) { - const auto p = ss.pixels[i]; - callback(i, p); - } +constexpr void walkPixels(TileSheet::SubSheet const&ss, int8_t, auto callback) noexcept { + for (std::size_t i = 0; i < ss.pixels.size(); ++i) { + callback(i, ss.pixels[i]); } } -void setPixel(TileSheet::SubSheet &ss, int8_t pBpp, uint64_t idx, uint8_t palIdx) noexcept; +void setPixel(TileSheet::SubSheet &ss, ox::Point const&pt, uint8_t palIdx) noexcept; -void setPixel(TileSheet::SubSheet &ss, int8_t pBpp, ox::Point const&pt, uint8_t palIdx) noexcept; - -ox::Error setPixelCount(TileSheet::SubSheet &ss, int8_t pBpp, std::size_t cnt) noexcept; +ox::Error setPixelCount(TileSheet::SubSheet &ss, std::size_t cnt) noexcept; /** * Gets a count of the pixels in this sheet, and not that of its children. - * @param pBpp bits per pixel, need for knowing how to count the pixels * @return a count of the pixels in this sheet */ [[nodiscard]] -unsigned pixelCnt(TileSheet::SubSheet const&ss, int8_t pBpp) noexcept; +unsigned pixelCnt(TileSheet::SubSheet const&ss) noexcept; /** * @@ -365,7 +441,7 @@ unsigned pixelCnt(TileSheet::SubSheet const&ss, int8_t pBpp) noexcept; * @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; +ox::Error resizeSubsheet(TileSheet::SubSheet &ss, ox::Size const&sz) noexcept; /** * validateSubSheetIdx takes a SubSheetIdx and moves the index to the @@ -522,6 +598,22 @@ OX_MODEL_BEGIN(TileSheetV4) OX_MODEL_FIELD(subsheet) OX_MODEL_END() +OX_MODEL_BEGIN(TileSheetV5::SubSheet) + OX_MODEL_FIELD(id) + OX_MODEL_FIELD(name) + OX_MODEL_FIELD(rows) + OX_MODEL_FIELD(columns) + OX_MODEL_FIELD(subsheets) + OX_MODEL_FIELD(pixels) +OX_MODEL_END() + +OX_MODEL_BEGIN(TileSheetV5) + OX_MODEL_FIELD(bpp) + OX_MODEL_FIELD(idIt) + OX_MODEL_FIELD(defaultPalette) + OX_MODEL_FIELD(subsheet) +OX_MODEL_END() + OX_MODEL_BEGIN(CompactTileSheetV1) OX_MODEL_FIELD(bpp) OX_MODEL_FIELD(defaultPalette) diff --git a/src/nostalgia/modules/gfx/src/keel/keelmodule.cpp b/src/nostalgia/modules/gfx/src/keel/keelmodule.cpp index 346df56e..6148fc51 100644 --- a/src/nostalgia/modules/gfx/src/keel/keelmodule.cpp +++ b/src/nostalgia/modules/gfx/src/keel/keelmodule.cpp @@ -23,6 +23,7 @@ static class: public keel::Module { TileSheetV1ToTileSheetV2Converter m_tileSheetV1ToTileSheetV2Converter; TileSheetV2ToTileSheetV3Converter m_tileSheetV2ToTileSheetV3Converter; TileSheetV3ToTileSheetV4Converter m_tileSheetV3ToTileSheetV4Converter; + TileSheetV4ToTileSheetV5Converter m_tileSheetV4ToTileSheetV5Converter; TileSheetToCompactTileSheetConverter m_tileSheetToCompactTileSheetConverter; public: @@ -38,6 +39,7 @@ static class: public keel::Module { keel::generateTypeDesc, keel::generateTypeDesc, keel::generateTypeDesc, + keel::generateTypeDesc, keel::generateTypeDesc, keel::generateTypeDesc, keel::generateTypeDesc, @@ -58,6 +60,7 @@ static class: public keel::Module { &m_tileSheetV1ToTileSheetV2Converter, &m_tileSheetV2ToTileSheetV3Converter, &m_tileSheetV3ToTileSheetV4Converter, + &m_tileSheetV4ToTileSheetV5Converter, &m_tileSheetToCompactTileSheetConverter, }; } diff --git a/src/nostalgia/modules/gfx/src/keel/typeconv.cpp b/src/nostalgia/modules/gfx/src/keel/typeconv.cpp index 466e69dd..28fc142d 100644 --- a/src/nostalgia/modules/gfx/src/keel/typeconv.cpp +++ b/src/nostalgia/modules/gfx/src/keel/typeconv.cpp @@ -133,6 +133,46 @@ ox::Error TileSheetV3ToTileSheetV4Converter::convert( return {}; } + +void TileSheetV4ToTileSheetV5Converter::convertSubsheet( + int const bpp, + TileSheetV4::SubSheet &src, + TileSheetV5::SubSheet &dst, + SubSheetId &idIt) noexcept { + dst.id = idIt; + dst.name = std::move(src.name); + dst.columns = src.columns; + dst.rows = src.rows; + if (bpp == 4) { + dst.pixels.reserve(2 * src.pixels.size()); + dst.pixels.resize(0); + for (auto const p : src.pixels) { + dst.pixels.emplace_back(static_cast(p & 0xf)); + dst.pixels.emplace_back(static_cast(p >> 4)); + } + oxAssert(dst.pixels.size() == src.pixels.size() *2, "mismatch"); + } else { + dst.pixels = std::move(src.pixels); + } + ++idIt; + dst.subsheets.resize(src.subsheets.size()); + for (auto i = 0u; i < src.subsheets.size(); ++i) { + convertSubsheet(bpp, src.subsheets[i], dst.subsheets[i], idIt); + } +} + +ox::Error TileSheetV4ToTileSheetV5Converter::convert( + keel::Context&, + TileSheetV4 &src, + TileSheetV5 &dst) const noexcept { + dst.bpp = src.bpp; + dst.idIt = src.idIt; + dst.defaultPalette = std::move(src.defaultPalette); + convertSubsheet(dst.bpp, src.subsheet, dst.subsheet, dst.idIt); + return {}; +} + + ox::Error TileSheetToCompactTileSheetConverter::convert( keel::Context&, TileSheet &src, diff --git a/src/nostalgia/modules/gfx/src/keel/typeconv.hpp b/src/nostalgia/modules/gfx/src/keel/typeconv.hpp index 1d52a13e..a5b7664d 100644 --- a/src/nostalgia/modules/gfx/src/keel/typeconv.hpp +++ b/src/nostalgia/modules/gfx/src/keel/typeconv.hpp @@ -56,6 +56,15 @@ class TileSheetV3ToTileSheetV4Converter: public keel::Converter { + static void convertSubsheet( + int bpp, + TileSheetV4::SubSheet &src, + TileSheetV5::SubSheet &dst, + SubSheetId &idIt) noexcept; + ox::Error convert(keel::Context&, TileSheetV4 &src, TileSheetV5 &dst) const noexcept override; +}; + class TileSheetToCompactTileSheetConverter: public keel::Converter { ox::Error convert(keel::Context&, TileSheet &src, CompactTileSheet &dst) const noexcept final; }; diff --git a/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/addsubsheetcommand.cpp b/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/addsubsheetcommand.cpp index 78574284..d9d3a740 100644 --- a/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/addsubsheetcommand.cpp +++ b/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/addsubsheetcommand.cpp @@ -28,12 +28,12 @@ ox::Error AddSubSheetCommand::redo() noexcept { auto &parent = getSubSheet(m_img, m_parentIdx); if (m_addedSheets.size() < 2) { auto i = parent.subsheets.size(); - parent.subsheets.emplace_back(m_img.idIt++, ox::sfmt("Subsheet {}", i), 1, 1, m_img.bpp); + parent.subsheets.emplace_back(m_img.idIt++, ox::sfmt("Subsheet {}", i), 1, 1); } else { parent.subsheets.emplace_back(m_img.idIt++, "Subsheet 0", parent.columns, parent.rows, std::move(parent.pixels)); parent.rows = 0; parent.columns = 0; - parent.subsheets.emplace_back(m_img.idIt++, "Subsheet 1", 1, 1, m_img.bpp); + parent.subsheets.emplace_back(m_img.idIt++, "Subsheet 1", 1, 1); } return {}; } diff --git a/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/cutpastecommand.cpp b/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/cutpastecommand.cpp index 86b0fbe3..c5aa5b51 100644 --- a/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/cutpastecommand.cpp +++ b/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/cutpastecommand.cpp @@ -38,7 +38,7 @@ CutPasteCommand::CutPasteCommand( auto const dstPt = p.pt + dstStart; if (dstPt.x <= dstEnd.x && dstPt.y <= dstEnd.y) { auto const idx = gfx::idx(ss, dstPt); - m_changes.emplace_back(static_cast(idx), p.colorIdx, getPixel(ss, m_img.bpp, idx)); + m_changes.emplace_back(static_cast(idx), p.colorIdx, getPixel(ss, idx)); } } } @@ -46,7 +46,7 @@ CutPasteCommand::CutPasteCommand( ox::Error CutPasteCommand::redo() noexcept { auto &subsheet = getSubSheet(m_img, m_subSheetIdx); for (const auto &c : m_changes) { - setPixel(subsheet, m_img.bpp, c.idx, static_cast(c.newPalIdx)); + subsheet.pixels[c.idx] = static_cast(c.newPalIdx); } return {}; } @@ -54,7 +54,7 @@ ox::Error CutPasteCommand::redo() noexcept { ox::Error CutPasteCommand::undo() noexcept { auto &subsheet = getSubSheet(m_img, m_subSheetIdx); for (const auto &c : m_changes) { - setPixel(subsheet, m_img.bpp, c.idx, static_cast(c.oldPalIdx)); + subsheet.pixels[c.idx] = static_cast(c.oldPalIdx); } return {}; } diff --git a/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/drawcommand.cpp b/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/drawcommand.cpp index c75a3e8e..b359e70a 100644 --- a/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/drawcommand.cpp +++ b/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/drawcommand.cpp @@ -15,7 +15,7 @@ DrawCommand::DrawCommand( m_subSheetIdx(std::move(subSheetIdx)), m_palIdx(palIdx) { auto &subsheet = getSubSheet(m_img, m_subSheetIdx); - m_changes.emplace_back(static_cast(idx), getPixel(subsheet, m_img.bpp, idx)); + m_changes.emplace_back(static_cast(idx), getPixel(subsheet, idx)); } DrawCommand::DrawCommand( @@ -28,20 +28,20 @@ DrawCommand::DrawCommand( m_palIdx(palIdx) { auto &subsheet = getSubSheet(m_img, m_subSheetIdx); for (auto const idx : idxList) { - m_changes.emplace_back(static_cast(idx), getPixel(subsheet, m_img.bpp, idx)); + m_changes.emplace_back(static_cast(idx), getPixel(subsheet, idx)); } } bool DrawCommand::append(std::size_t idx) noexcept { auto &subsheet = getSubSheet(m_img, m_subSheetIdx); - if (m_changes.back().value->idx != idx && getPixel(subsheet, m_img.bpp, idx) != m_palIdx) { + if (m_changes.back().value->idx != idx && getPixel(subsheet, idx) != m_palIdx) { // duplicate entries are bad auto existing = ox::find_if(m_changes.cbegin(), m_changes.cend(), [idx](auto const&c) { return c.idx == idx; }); if (existing == m_changes.cend()) { - m_changes.emplace_back(static_cast(idx), getPixel(subsheet, m_img.bpp, idx)); - setPixel(subsheet, m_img.bpp, idx, static_cast(m_palIdx)); + m_changes.emplace_back(static_cast(idx), getPixel(subsheet, idx)); + subsheet.pixels[idx] = static_cast(m_palIdx); return true; } } @@ -59,7 +59,7 @@ bool DrawCommand::append(ox::Vector const&idxList) noexcept { ox::Error DrawCommand::redo() noexcept { auto &subsheet = getSubSheet(m_img, m_subSheetIdx); for (auto const&c : m_changes) { - setPixel(subsheet, m_img.bpp, c.idx, static_cast(m_palIdx)); + subsheet.pixels[c.idx] = static_cast(m_palIdx); } return {}; } @@ -67,7 +67,7 @@ ox::Error DrawCommand::redo() noexcept { ox::Error DrawCommand::undo() noexcept { auto &subsheet = getSubSheet(m_img, m_subSheetIdx); for (auto const&c : m_changes) { - setPixel(subsheet, m_img.bpp, c.idx, static_cast(c.oldPalIdx)); + subsheet.pixels[c.idx] = static_cast(c.oldPalIdx); } return {}; } diff --git a/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/updatesubsheetcommand.cpp b/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/updatesubsheetcommand.cpp index 7038320b..03df8255 100644 --- a/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/updatesubsheetcommand.cpp +++ b/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/commands/updatesubsheetcommand.cpp @@ -17,7 +17,7 @@ gfx::UpdateSubSheetCommand::UpdateSubSheetCommand( m_sheet{getSubSheet(m_img, m_idx)} { m_sheet = getSubSheet(m_img, m_idx); m_sheet.name = std::move(name); - OX_THROW_ERROR(resizeSubsheet(m_sheet, m_img.bpp, {cols, rows})); + OX_THROW_ERROR(resizeSubsheet(m_sheet, {cols, rows})); } ox::Error UpdateSubSheetCommand::redo() noexcept { diff --git a/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/tilesheeteditormodel.cpp b/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/tilesheeteditormodel.cpp index df31d5b3..4a5117f7 100644 --- a/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/tilesheeteditormodel.cpp +++ b/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/tilesheeteditormodel.cpp @@ -67,7 +67,7 @@ void TileSheetEditorModel::cut() { iterateSelectionRows(*m_selection, [&](int const x, int const y) { auto pt = ox::Point{x, y}; auto const idx = gfx::idx(s, pt); - auto const c = getPixel(s, m_img.bpp, idx); + auto const c = getPixel(s, idx); pt -= m_selection->a; cb->addPixel(pt, c); blankCb.addPixel(pt, 0); @@ -88,7 +88,7 @@ void TileSheetEditorModel::copy() { auto pt = ox::Point{x, y}; const auto&s = activeSubSheet(); const auto idx = gfx::idx(s, pt); - const auto c = getPixel(s, m_img.bpp, idx); + const auto c = getPixel(s, idx); pt -= m_selection->a; cb->addPixel(pt, c); }); @@ -159,7 +159,7 @@ void TileSheetEditorModel::drawCommand(ox::Point const&pt, std::size_t const pal const auto idx = gfx::idx(activeSubSheet, pt); if (m_ongoingDrawCommand) { m_updated = m_updated || m_ongoingDrawCommand->append(idx); - } else if (getPixel(activeSubSheet, m_img.bpp, idx) != palIdx) { + } else if (getPixel(activeSubSheet, idx) != palIdx) { pushCommand(ox::make( m_img, m_activeSubsSheetIdx, idx, static_cast(palIdx))); } @@ -206,7 +206,7 @@ void TileSheetEditorModel::fill(ox::Point const&pt, int const palIdx) noexcept { return; } ox::Array updateMap = {}; - auto const oldColor = getPixel(activeSubSheet, m_img.bpp, pt); + auto const oldColor = getPixel(activeSubSheet, pt); getFillPixels(activeSubSheet, updateMap, pt, oldColor); ox::Vector idxList; auto i = gfx::idx(activeSubSheet, pt) / PixelsPerTile * PixelsPerTile; @@ -219,7 +219,7 @@ void TileSheetEditorModel::fill(ox::Point const&pt, int const palIdx) noexcept { // do updates to sheet if (m_ongoingDrawCommand) { m_updated = m_updated || m_ongoingDrawCommand->append(idxList); - } else if (getPixel(activeSubSheet, m_img.bpp, pt) != palIdx) { + } else if (getPixel(activeSubSheet, pt) != palIdx) { pushCommand(ox::make(m_img, m_activeSubsSheetIdx, idxList, palIdx)); } } @@ -298,7 +298,7 @@ void TileSheetEditorModel::getFillPixels( int const oldColor) const noexcept { auto const idx = ptToIdx(pt, activeSubSheet.columns); auto const relIdx = idx % PixelsPerTile; - if (pixels[relIdx] || getPixel(activeSubSheet, m_img.bpp, idx) != oldColor) { + if (pixels[relIdx] || getPixel(activeSubSheet, idx) != oldColor) { return; } // mark pixels to update diff --git a/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/tilesheetpixels.cpp b/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/tilesheetpixels.cpp index c12ebf31..a594e320 100644 --- a/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/tilesheetpixels.cpp +++ b/src/nostalgia/modules/gfx/src/studio/tilesheeteditor/tilesheetpixels.cpp @@ -127,6 +127,7 @@ void TileSheetPixels::setBufferObjects(ox::Vec2 const&paneSize) noexcept { auto const height = subSheet.rows * TileHeight; auto const pixels = static_cast(width) * static_cast(height); auto const vboLen = static_cast(s_programSrc.vboLen); + oxAssert(subSheet.pixels.size() == pixels, "incorrect pixels"); m_bufferSet.vertices.resize(pixels * vboLen); m_bufferSet.elements.resize(pixels * VertexEboLength); // set pixels diff --git a/src/nostalgia/modules/gfx/src/tilesheet.cpp b/src/nostalgia/modules/gfx/src/tilesheet.cpp index 77967b4b..1baa5e14 100644 --- a/src/nostalgia/modules/gfx/src/tilesheet.cpp +++ b/src/nostalgia/modules/gfx/src/tilesheet.cpp @@ -28,21 +28,20 @@ static TileSheet::SubSheet const *getSubsheet(TileSheet::SubSheet const&ss, SubS } [[nodiscard]] -static size_t getTileCnt(TileSheet::SubSheet const&ss, int const bpp) noexcept { +static size_t getTileCnt(TileSheet::SubSheet const&ss) noexcept { if (ss.subsheets.empty()) { - auto const bytesPerTile = bpp == 4 ? 32u : 64u; - return ss.pixels.size() / bytesPerTile; + return ss.pixels.size() / PixelsPerTile; } else { size_t out{}; for (auto const&child: ss.subsheets) { - out += getTileCnt(child, bpp); + out += getTileCnt(child); } return out; } } size_t getTileCnt(TileSheet const&ts) noexcept { - return getTileCnt(ts.subsheet, ts.bpp); + return getTileCnt(ts.subsheet); } TileSheet::SubSheet const *getSubsheet(TileSheet const&ts, SubSheetId const id) noexcept { @@ -52,44 +51,35 @@ TileSheet::SubSheet const *getSubsheet(TileSheet const&ts, SubSheetId const id) static ox::Optional getPixelIdx( TileSheet::SubSheet const&ss, SubSheetId const id, - size_t &idx, - int8_t const bpp) noexcept { + size_t &idx) noexcept { for (auto const&child: ss.subsheets) { if (child.id == id) { return ox::Optional(ox::in_place, idx); } - if (auto out = getPixelIdx(child, id, idx, bpp)) { + if (auto out = getPixelIdx(child, id, idx)) { return out; } - idx += pixelCnt(child, bpp); + idx += pixelCnt(child); } return ox::Optional{}; } ox::Optional getTileIdx(TileSheet const&ts, SubSheetId const id) noexcept { size_t idx{}; - auto const out = getPixelIdx(ts.subsheet, id, idx, ts.bpp); + auto const out = getPixelIdx(ts.subsheet, id, idx); return out ? ox::Optional{ox::in_place, *out / PixelsPerTile} : out; } -uint8_t getPixel4Bpp(TileSheet::SubSheet const&ss, std::size_t idx) noexcept { - if (idx & 1) { - return ss.pixels[idx / 2] >> 4; - } else { - return ss.pixels[idx / 2] & 0b0000'1111; - } -} - -uint8_t getPixel8Bpp(TileSheet::SubSheet const&ss, std::size_t idx) noexcept { +uint8_t getPixel4Bpp(TileSheet::SubSheet const&ss, std::size_t const idx) noexcept { return ss.pixels[idx]; } -uint8_t getPixel(TileSheet::SubSheet const&ss, int8_t pBpp, std::size_t idx) noexcept { - if (pBpp == 4) { - return getPixel4Bpp(ss, idx); - } else { - return getPixel8Bpp(ss, idx); - } +uint8_t getPixel8Bpp(TileSheet::SubSheet const&ss, std::size_t const idx) noexcept { + return ss.pixels[idx]; +} + +uint8_t getPixel(TileSheet::SubSheet const&ss, std::size_t const idx) noexcept { + return ss.pixels[idx]; } uint8_t getPixel4Bpp(TileSheet::SubSheet const&ss, ox::Point const&pt) noexcept { @@ -102,73 +92,48 @@ uint8_t getPixel8Bpp(TileSheet::SubSheet const&ss, ox::Point const&pt) noexcept 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, ox::Point const&pt) noexcept { const auto idx = ptToIdx(pt, ss.columns); - return getPixel(ss, pBpp, idx); + return getPixel(ss, idx); } -static void setPixel(ox::Vector &pixels, int8_t pBpp, uint64_t idx, uint8_t palIdx) noexcept { - auto &pixel = 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(TileSheet::SubSheet &ss, int8_t pBpp, uint64_t idx, uint8_t palIdx) noexcept { - setPixel(ss.pixels, pBpp, idx, palIdx); -} - -static void setPixel(ox::Vector &pixels, int columns, int8_t pBpp, ox::Point const&pt, uint8_t palIdx) noexcept { +static void setPixel( + ox::Vector &pixels, + int const columns, + ox::Point const&pt, + uint8_t const palIdx) noexcept { const auto idx = ptToIdx(pt, columns); - setPixel(pixels, pBpp, idx, palIdx); + pixels[idx] = palIdx; } -void setPixel(TileSheet::SubSheet &ss, int8_t pBpp, ox::Point const&pt, uint8_t palIdx) noexcept { +void setPixel(TileSheet::SubSheet &ss, ox::Point const&pt, uint8_t const palIdx) noexcept { const auto idx = ptToIdx(pt, ss.columns); - setPixel(ss, pBpp, idx, palIdx); + ss.pixels[idx] = palIdx; } -static ox::Error setPixelCount(ox::Vector &pixels, int8_t pBpp, std::size_t cnt) noexcept { - size_t sz{}; - switch (pBpp) { - case 4: - sz = cnt / 2; - break; - case 8: - sz = cnt; - break; - default: - return ox::Error(1, "Invalid pBpp used for TileSheet::SubSheet::setPixelCount"); - } - pixels.reserve(sz); - pixels.resize(sz); +static ox::Error setPixelCount(ox::Vector &pixels, std::size_t const cnt) noexcept { + pixels.reserve(cnt); + pixels.resize(cnt); return {}; } -ox::Error setPixelCount(TileSheet::SubSheet &ss, int8_t pBpp, std::size_t cnt) noexcept { - return setPixelCount(ss.pixels, pBpp, cnt); +ox::Error setPixelCount(TileSheet::SubSheet &ss, std::size_t const cnt) noexcept { + return setPixelCount(ss.pixels, cnt); } -unsigned pixelCnt(TileSheet::SubSheet const&ss, int8_t pBpp) noexcept { - const auto pixelsSize = static_cast(ss.pixels.size()); - return pBpp == 4 ? pixelsSize * 2 : pixelsSize; +unsigned pixelCnt(TileSheet::SubSheet const&ss) noexcept { + return static_cast(ss.pixels.size()); } -ox::Error resizeSubsheet(TileSheet::SubSheet &ss, int8_t pBpp, ox::Size const&sz) noexcept { +ox::Error resizeSubsheet(TileSheet::SubSheet &ss, ox::Size const&sz) noexcept { ox::Vector out; - OX_RETURN_ERROR(setPixelCount(out, pBpp, static_cast(sz.width * sz.height) * PixelsPerTile)); + OX_RETURN_ERROR(setPixelCount(out, static_cast(sz.width * sz.height) * PixelsPerTile)); auto const w = ox::min(ss.columns, sz.width) * TileWidth; auto const h = ox::min(ss.rows, 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); + auto const palIdx = getPixel(ss, {x, y}); + setPixel(out, sz.width, {x, y}, palIdx); } } ss.columns = sz.width; @@ -177,7 +142,7 @@ ox::Error resizeSubsheet(TileSheet::SubSheet &ss, int8_t pBpp, ox::Size const&sz return {}; } -ox::Result getNameFor(TileSheet::SubSheet const&ss, SubSheetId pId) noexcept { +ox::Result getNameFor(TileSheet::SubSheet const&ss, SubSheetId const pId) noexcept { if (ss.id == pId) { return ox::StringView(ss.name); } @@ -193,7 +158,7 @@ ox::Result getNameFor(TileSheet::SubSheet const&ss, SubSheetId p TileSheet::SubSheetIdx validateSubSheetIdx( TileSheet::SubSheetIdx &&pIdx, - std::size_t pIdxIt, + std::size_t const pIdxIt, TileSheet::SubSheet const&pSubsheet) noexcept { if (pIdxIt >= pIdx.size()) { return std::move(pIdx); @@ -216,9 +181,9 @@ TileSheet::SubSheetIdx validateSubSheetIdx(TileSheet const&ts, TileSheet::SubShe return validateSubSheetIdx(std::move(idx), 0, ts.subsheet); } -const TileSheet::SubSheet &getSubSheet( +TileSheet::SubSheet const&getSubSheet( TileSheet::SubSheetIdx const&idx, - std::size_t idxIt, + std::size_t const idxIt, TileSheet::SubSheet const&pSubsheet) noexcept { if (idxIt == idx.size()) { return pSubsheet; @@ -232,7 +197,7 @@ const TileSheet::SubSheet &getSubSheet( TileSheet::SubSheet &getSubSheet( TileSheet::SubSheetIdx const&idx, - std::size_t idxIt, + std::size_t const idxIt, TileSheet::SubSheet &pSubsheet) noexcept { if (idxIt == idx.size()) { return pSubsheet; @@ -251,10 +216,10 @@ TileSheet::SubSheet &getSubSheet(TileSheet &ts, TileSheet::SubSheetIdx const&idx ox::Error addSubSheet(TileSheet &ts, TileSheet::SubSheetIdx const&idx) noexcept { auto &parent = getSubSheet(ts, idx); if (parent.subsheets.size() < 2) { - parent.subsheets.emplace_back(++ts.idIt, ox::sfmt("Subsheet {}", parent.subsheets.size()), 1, 1, ts.bpp); + parent.subsheets.emplace_back(++ts.idIt, ox::sfmt("Subsheet {}", parent.subsheets.size()), 1, 1); } else { - parent.subsheets.emplace_back(++ts.idIt, "Subsheet 0", parent.columns, parent.rows, ts.bpp); - parent.subsheets.emplace_back(++ts.idIt, "Subsheet 1", 1, 1, ts.bpp); + parent.subsheets.emplace_back(++ts.idIt, "Subsheet 0", parent.columns, parent.rows); + parent.subsheets.emplace_back(++ts.idIt, "Subsheet 1", 1, 1); } return ox::Error(0); } @@ -262,7 +227,7 @@ ox::Error addSubSheet(TileSheet &ts, TileSheet::SubSheetIdx const&idx) noexcept ox::Error rmSubSheet( TileSheet &ts, TileSheet::SubSheetIdx const&idx, - std::size_t idxIt, + std::size_t const idxIt, TileSheet::SubSheet &pSubsheet) noexcept { if (idxIt == idx.size() - 1) { return pSubsheet.subsheets.erase(idx[idxIt]).error; @@ -315,18 +280,12 @@ uint8_t getPixel8Bpp( ox::Pair get2Pixels4Bpp( CompactTileSheet const&ts, size_t const idx) noexcept { - oxAssert(ts.bpp == 4, "TileSheet::getPixel4Bpp: wrong bpp"); - auto const out = ts.pixels[idx / 2]; - return { - static_cast(out & 0x0f), - static_cast(out >> 4), - }; + return get2Pixels8Bpp(ts, idx); } ox::Pair get2Pixels8Bpp( CompactTileSheet const&ts, size_t const idx) noexcept { - oxAssert(ts.bpp == 8, "TileSheet::getPixel8Bpp: wrong bpp"); return { static_cast(ts.pixels[idx]), static_cast(ts.pixels[idx + 1]), @@ -336,7 +295,7 @@ ox::Pair get2Pixels8Bpp( static ox::Result getIdFor( TileSheet::SubSheet const&ss, ox::SpanView const&pNamePath, - std::size_t pIt = 0) noexcept { + std::size_t const pIt = 0) noexcept { for (auto &sub : ss.subsheets) { if (sub.name == pNamePath[pIt]) { if (pIt == pNamePath.size()) { @@ -358,8 +317,7 @@ ox::Result getIdFor(TileSheet const&ts, ox::StringViewCR path) noexc static ox::Result getTileOffset( TileSheet::SubSheet const&ss, ox::SpanView const&pNamePath, - int8_t pBpp, - std::size_t pIt = 0, + std::size_t const pIt = 0, uint32_t pCurrentTotal = 0) noexcept { // pIt == pNamePath.size() - 1 && if (ss.name != pNamePath[pIt]) { @@ -370,44 +328,52 @@ static ox::Result getTileOffset( } for (auto &sub : ss.subsheets) { auto [offset, err] = getTileOffset( - sub, pNamePath, pBpp, pIt + 1, pCurrentTotal); + sub, pNamePath, pIt + 1, pCurrentTotal); if (!err) { return offset; } - // Possible bug? Shoud this be usinga a recursive version of + // Possible bug? Should this be using a recursive version of // pixelCnt will count pixels in subsheets of sub as well. - pCurrentTotal += pixelCnt(sub, pBpp) / PixelsPerTile; + pCurrentTotal += pixelCnt(sub) / PixelsPerTile; } return ox::Error(1, "SubSheet not found"); } ox::Result getTileOffset(TileSheet const&ts, ox::StringViewCR pNamePath) noexcept { - return gfx::getTileOffset(ts.subsheet, ox::split<8>(pNamePath, '.'), ts.bpp); + return gfx::getTileOffset(ts.subsheet, ox::split<8>(pNamePath, '.')); } -ox::Result getNameFor(TileSheet &ts, SubSheetId pId) noexcept { +ox::Result getNameFor(TileSheet &ts, SubSheetId const pId) noexcept { return gfx::getNameFor(ts.subsheet, pId); } -ox::Result getNameFor(TileSheet const&ts, SubSheetId pId) noexcept { +ox::Result getNameFor(TileSheet const&ts, SubSheetId const pId) noexcept { return gfx::getNameFor(ts.subsheet, pId); } -static void readPixelsTo(TileSheet::SubSheet &ss, ox::Vector &pPixels) noexcept { +static void readPixelsTo(TileSheet::SubSheet &ss, int const pBpp, ox::Vector &pPixels) noexcept { if (!ss.subsheets.empty()) { for (auto &s: ss.subsheets) { - readPixelsTo(s, pPixels); + readPixelsTo(s, pBpp, pPixels); } } else { - for (auto p : ss.pixels) { - pPixels.emplace_back(p); + if (pBpp == 4) { + for (size_t i{}; i < ss.pixels.size() - 1; i += 2) { + auto const p1 = ss.pixels[i]; + auto const p2 = ss.pixels[i + 1]; + pPixels.emplace_back(static_cast(p1 | (p2 << 4))); + } + } else { + for (auto const p : ss.pixels) { + pPixels.emplace_back(p); + } } } } ox::Vector pixels(TileSheet &ts) noexcept { ox::Vector out; - readPixelsTo(ts.subsheet, out); + readPixelsTo(ts.subsheet, ts.bpp, out); return out; } @@ -415,7 +381,7 @@ ox::Vector pixels(TileSheet &ts) noexcept { ox::Vector resizeTileSheetData( ox::Vector const&srcPixels, ox::Size const&srcSize, - int scale) noexcept { + int const scale) noexcept { ox::Vector dst; auto dstWidth = srcSize.width * scale; auto dstHeight = srcSize.height * scale;