[nostalgia/core] Upgrade TileSheet format to support subsheets and add conversion system
This commit is contained in:
parent
3c44c86e91
commit
7ac7909510
@ -49,6 +49,7 @@ add_library(
|
||||
NostalgiaCore
|
||||
gfx.cpp
|
||||
media.cpp
|
||||
typeconv.cpp
|
||||
${NOSTALGIA_CORE_IMPL_SRC}
|
||||
)
|
||||
|
||||
@ -79,6 +80,7 @@ install(
|
||||
gfx.hpp
|
||||
input.hpp
|
||||
media.hpp
|
||||
typeconv.hpp
|
||||
DESTINATION
|
||||
include/nostalgia/core
|
||||
)
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "gfx.hpp"
|
||||
#include "input.hpp"
|
||||
#include "media.hpp"
|
||||
#include "typeconv.hpp"
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
|
@ -35,7 +35,7 @@ struct Palette {
|
||||
ox::Vector<Color16> colors;
|
||||
};
|
||||
|
||||
struct TileSheet {
|
||||
struct TileSheetV1 {
|
||||
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.NostalgiaGraphic";
|
||||
static constexpr auto TypeVersion = 1;
|
||||
int8_t bpp = 0;
|
||||
@ -48,7 +48,7 @@ struct TileSheet {
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr uint8_t getPixel4Bpp(std::size_t idx) const noexcept {
|
||||
oxAssert(bpp == 4, "NostalgiaGraphic::getPixel4Bpp: wrong bpp");
|
||||
oxAssert(bpp == 4, "TileSheetV1::getPixel4Bpp: wrong bpp");
|
||||
if (idx & 1) {
|
||||
return this->pixels[idx / 2] >> 4;
|
||||
} else {
|
||||
@ -58,7 +58,7 @@ struct TileSheet {
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr uint8_t getPixel8Bpp(std::size_t idx) const noexcept {
|
||||
oxAssert(bpp == 8, "NostalgiaGraphic::getPixel8Bpp: wrong bpp");
|
||||
oxAssert(bpp == 8, "TileSheetV1::getPixel8Bpp: wrong bpp");
|
||||
return this->pixels[idx];
|
||||
}
|
||||
|
||||
@ -73,14 +73,14 @@ struct TileSheet {
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto getPixel4Bpp(const geo::Point &pt) const noexcept {
|
||||
oxAssert(bpp == 4, "NostalgiaGraphic::getPixel4Bpp: wrong bpp");
|
||||
oxAssert(bpp == 4, "TileSheetV1::getPixel4Bpp: wrong bpp");
|
||||
const auto idx = ptToIdx(pt, this->columns);
|
||||
return getPixel4Bpp(idx);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto getPixel8Bpp(const geo::Point &pt) const noexcept {
|
||||
oxAssert(bpp == 8, "NostalgiaGraphic::getPixel8Bpp: wrong bpp");
|
||||
oxAssert(bpp == 8, "TileSheetV1::getPixel8Bpp: wrong bpp");
|
||||
const auto idx = ptToIdx(pt, this->columns);
|
||||
return getPixel8Bpp(idx);
|
||||
}
|
||||
@ -92,7 +92,7 @@ struct TileSheet {
|
||||
}
|
||||
|
||||
constexpr void setPixel(uint64_t idx, uint8_t palIdx) noexcept {
|
||||
auto &pixel = this->pixels[idx / 2];
|
||||
auto &pixel = this->pixels[idx / 2];
|
||||
if (bpp == 4) {
|
||||
if (idx & 1) {
|
||||
pixel = (pixel & 0b0000'1111) | (palIdx << 4);
|
||||
@ -110,11 +110,144 @@ struct TileSheet {
|
||||
}
|
||||
};
|
||||
|
||||
struct TileSheet {
|
||||
using SubSheetIdx = ox::Vector<std::size_t, 4>;
|
||||
|
||||
struct SubSheet {
|
||||
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.TileSheet.SubSheet";
|
||||
static constexpr auto TypeVersion = "net.drinkingtea.nostalgia.core.TileSheet.SubSheet";
|
||||
ox::BString<32> name;
|
||||
std::size_t begin = 0;
|
||||
std::size_t size = 0;
|
||||
int rows = 1;
|
||||
int columns = 1;
|
||||
ox::Vector<SubSheet> subsheets;
|
||||
};
|
||||
|
||||
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.TileSheet";
|
||||
static constexpr auto TypeVersion = 2;
|
||||
int8_t bpp = 0;
|
||||
// rows and columns are really only used by TileSheetEditor
|
||||
ox::FileAddress defaultPalette;
|
||||
Palette pal;
|
||||
ox::Vector<uint8_t> pixels;
|
||||
SubSheet subsheet;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const auto &getSubSheet(const SubSheetIdx &idx, std::size_t idxIt, const SubSheet *pSubsheet) const noexcept {
|
||||
if (idxIt == idx.size()) {
|
||||
return *pSubsheet;
|
||||
}
|
||||
return getSubSheet(idx, idxIt + 1, &pSubsheet->subsheets[idx[idxIt]]);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const auto &getSubSheet(const SubSheetIdx &idx) const noexcept {
|
||||
return getSubSheet(idx, 0, &subsheet);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto &getSubSheet(const SubSheetIdx &idx, std::size_t idxIt, const SubSheet *pSubsheet) noexcept {
|
||||
if (idxIt == idx.size()) {
|
||||
return *pSubsheet;
|
||||
}
|
||||
return getSubSheet(idx, idxIt + 1, &pSubsheet->subsheets[idx[idxIt]]);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto &getSubSheet(const SubSheetIdx &idx) noexcept {
|
||||
return getSubSheet(idx, 0, &subsheet);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const auto &columns(const SubSheetIdx &idx = {}) const noexcept {
|
||||
return getSubSheet(idx).columns;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const auto &rows(const SubSheetIdx &idx = {}) const noexcept {
|
||||
return getSubSheet(idx).rows;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto &columns(const SubSheetIdx &idx = {}) noexcept {
|
||||
return getSubSheet(idx).columns;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto &rows(const SubSheetIdx &idx = {}) noexcept {
|
||||
return getSubSheet(idx).rows;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr uint8_t getPixel4Bpp(std::size_t idx) const noexcept {
|
||||
oxAssert(bpp == 4, "TileSheetV1::getPixel4Bpp: wrong bpp");
|
||||
if (idx & 1) {
|
||||
return this->pixels[idx / 2] >> 4;
|
||||
} else {
|
||||
return this->pixels[idx / 2] & 0b0000'1111;
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr uint8_t getPixel8Bpp(std::size_t idx) const noexcept {
|
||||
oxAssert(bpp == 8, "TileSheetV1::getPixel8Bpp: wrong bpp");
|
||||
return this->pixels[idx];
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto getPixel(std::size_t idx) const noexcept {
|
||||
if (this->bpp == 4) {
|
||||
return getPixel4Bpp(idx);
|
||||
} else {
|
||||
return getPixel8Bpp(idx);
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto getPixel4Bpp(const geo::Point &pt, const SubSheetIdx &subsheetIdx) const noexcept {
|
||||
oxAssert(bpp == 4, "TileSheetV1::getPixel4Bpp: wrong bpp");
|
||||
const auto idx = ptToIdx(pt, this->getSubSheet(subsheetIdx).columns);
|
||||
return getPixel4Bpp(idx);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto getPixel8Bpp(const geo::Point &pt, const SubSheetIdx &subsheetIdx) const noexcept {
|
||||
oxAssert(bpp == 8, "TileSheetV1::getPixel8Bpp: wrong bpp");
|
||||
const auto idx = ptToIdx(pt, this->getSubSheet(subsheetIdx).columns);
|
||||
return getPixel8Bpp(idx);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto getPixel(const geo::Point &pt, const SubSheetIdx &subsheetIdx) const noexcept {
|
||||
const auto idx = ptToIdx(pt, this->getSubSheet(subsheetIdx).columns);
|
||||
return getPixel(idx);
|
||||
}
|
||||
|
||||
constexpr void setPixel(uint64_t idx, uint8_t palIdx) noexcept {
|
||||
auto &pixel = this->pixels[idx / 2];
|
||||
if (bpp == 4) {
|
||||
if (idx & 1) {
|
||||
pixel = (pixel & 0b0000'1111) | (palIdx << 4);
|
||||
} else {
|
||||
pixel = (pixel & 0b1111'0000) | (palIdx);
|
||||
}
|
||||
} else {
|
||||
pixel = palIdx;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr void setPixel(const SubSheetIdx &subsheetIdx, const geo::Point &pt, uint8_t palIdx) noexcept {
|
||||
const auto idx = ptToIdx(pt, this->getSubSheet(subsheetIdx).columns);
|
||||
setPixel(idx, palIdx);
|
||||
}
|
||||
};
|
||||
|
||||
oxModelBegin(Palette)
|
||||
oxModelField(colors)
|
||||
oxModelEnd()
|
||||
|
||||
oxModelBegin(TileSheet)
|
||||
oxModelBegin(TileSheetV1)
|
||||
oxModelField(bpp)
|
||||
oxModelField(rows)
|
||||
oxModelField(columns)
|
||||
@ -123,6 +256,23 @@ oxModelBegin(TileSheet)
|
||||
oxModelField(pixels)
|
||||
oxModelEnd()
|
||||
|
||||
oxModelBegin(TileSheet)
|
||||
oxModelField(bpp)
|
||||
oxModelField(defaultPalette)
|
||||
oxModelField(pal)
|
||||
oxModelField(pixels)
|
||||
oxModelField(subsheet)
|
||||
oxModelEnd()
|
||||
|
||||
oxModelBegin(TileSheet::SubSheet)
|
||||
oxModelField(name);
|
||||
oxModelField(begin);
|
||||
oxModelField(size);
|
||||
oxModelField(rows);
|
||||
oxModelField(columns);
|
||||
oxModelField(subsheets)
|
||||
oxModelEnd()
|
||||
|
||||
struct Sprite {
|
||||
unsigned idx = 0;
|
||||
unsigned x = 0;
|
||||
|
@ -4,27 +4,40 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ox/std/defines.hpp>
|
||||
|
||||
#include <ox/claw/claw.hpp>
|
||||
#include <ox/fs/fs.hpp>
|
||||
|
||||
#include "context.hpp"
|
||||
#include "typeconv.hpp"
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
template<typename T>
|
||||
ox::Result<AssetRef<T>> readObj(Context *ctx, const ox::FileAddress &file, bool forceLoad = false) noexcept {
|
||||
#ifndef OX_BARE_METAL
|
||||
constexpr auto readConvert = [](const ox::Buffer &buff) -> ox::Result<T> {
|
||||
auto [obj, err] = ox::readClaw<T>(buff);
|
||||
if (err) {
|
||||
if (err != ox::Error_ClawTypeVersionMismatch && err != ox::Error_ClawTypeMismatch) {
|
||||
return err;
|
||||
}
|
||||
oxReturnError(convert(buff, T::TypeName, T::TypeVersion, &obj));
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
oxRequire(path, file.getPath());
|
||||
if (forceLoad) {
|
||||
oxRequire(buff, ctx->rom->read(file));
|
||||
oxRequire(obj, ox::readClaw<T>(buff));
|
||||
oxRequire(obj, readConvert(buff));
|
||||
oxRequire(cached, ctx->assetManager.template setAsset(path, obj));
|
||||
return cached;
|
||||
} else {
|
||||
auto [cached, err] = ctx->assetManager.template getAsset<T>(path);
|
||||
if (err) {
|
||||
oxRequire(buff, ctx->rom->read(file));
|
||||
oxRequire(obj, ox::readClaw<T>(buff));
|
||||
oxRequire(obj, readConvert(buff));
|
||||
oxReturnError(ctx->assetManager.template setAsset(path, obj).moveTo(&cached));
|
||||
}
|
||||
return cached;
|
||||
|
@ -47,7 +47,7 @@ class TileSheetEditorImGui: public studio::Editor {
|
||||
|
||||
void draw(core::Context*) noexcept override;
|
||||
|
||||
virtual studio::UndoStack *undoStack() noexcept override;
|
||||
studio::UndoStack *undoStack() noexcept final;
|
||||
|
||||
protected:
|
||||
void saveItem() override;
|
||||
|
@ -40,8 +40,8 @@ void TileSheetEditor::draw() noexcept {
|
||||
|
||||
void TileSheetEditor::scrollV(const geo::Vec2 &paneSz, float wheel, bool zoomMod) noexcept {
|
||||
const auto pixelSize = m_pixelsDrawer.pixelSize(paneSz);
|
||||
const ImVec2 sheetSize(pixelSize.x * static_cast<float>(img().columns) * TileWidth,
|
||||
pixelSize.y * static_cast<float>(img().rows) * TileHeight);
|
||||
const ImVec2 sheetSize(pixelSize.x * static_cast<float>(img().columns()) * TileWidth,
|
||||
pixelSize.y * static_cast<float>(img().rows()) * TileHeight);
|
||||
if (zoomMod) {
|
||||
m_pixelSizeMod = ox::clamp(m_pixelSizeMod + wheel * 0.02f, 0.55f, 2.f);
|
||||
m_pixelsDrawer.setPixelSizeMod(m_pixelSizeMod);
|
||||
@ -57,8 +57,8 @@ void TileSheetEditor::scrollV(const geo::Vec2 &paneSz, float wheel, bool zoomMod
|
||||
|
||||
void TileSheetEditor::scrollH(const geo::Vec2 &paneSz, float wheelh) noexcept {
|
||||
const auto pixelSize = m_pixelsDrawer.pixelSize(paneSz);
|
||||
const ImVec2 sheetSize(pixelSize.x * static_cast<float>(img().columns) * TileWidth,
|
||||
pixelSize.y * static_cast<float>(img().rows) * TileHeight);
|
||||
const ImVec2 sheetSize(pixelSize.x * static_cast<float>(img().columns()) * TileWidth,
|
||||
pixelSize.y * static_cast<float>(img().rows()) * TileHeight);
|
||||
m_scrollOffset.x += wheelh * 0.1f;
|
||||
m_scrollOffset.x = ox::clamp(m_scrollOffset.x, -(sheetSize.x / 2), 0.f);
|
||||
}
|
||||
|
@ -25,9 +25,9 @@ void TileSheetEditorModel::paste() {
|
||||
|
||||
void TileSheetEditorModel::drawCommand(const geo::Point &pt, std::size_t palIdx) noexcept {
|
||||
if (m_ongoingDrawCommand) {
|
||||
m_updated = m_ongoingDrawCommand->append(ptToIdx(pt, m_img.columns));
|
||||
m_updated = m_ongoingDrawCommand->append(ptToIdx(pt, m_img.columns()));
|
||||
} else {
|
||||
const auto idx = ptToIdx(pt, m_img.columns);
|
||||
const auto idx = ptToIdx(pt, m_img.columns());
|
||||
if (m_img.getPixel(idx) != palIdx) {
|
||||
pushCommand(new DrawCommand(&m_updated, &m_img, idx, palIdx));
|
||||
}
|
||||
@ -48,7 +48,7 @@ void TileSheetEditorModel::ackUpdate() noexcept {
|
||||
|
||||
void TileSheetEditorModel::getFillPixels(bool *pixels, const geo::Point &pt, int oldColor) const noexcept {
|
||||
const auto tileIdx = [this](const geo::Point &pt) noexcept {
|
||||
return ptToIdx(pt, img().columns) / PixelsPerTile;
|
||||
return ptToIdx(pt, img().columns()) / PixelsPerTile;
|
||||
};
|
||||
// get points
|
||||
const auto leftPt = pt + geo::Point(-1, 0);
|
||||
@ -56,11 +56,11 @@ void TileSheetEditorModel::getFillPixels(bool *pixels, const geo::Point &pt, int
|
||||
const auto topPt = pt + geo::Point(0, -1);
|
||||
const auto bottomPt = pt + geo::Point(0, 1);
|
||||
// calculate indices
|
||||
const auto idx = ptToIdx(pt, m_img.columns);
|
||||
const auto leftIdx = ptToIdx(leftPt, m_img.columns);
|
||||
const auto rightIdx = ptToIdx(rightPt, m_img.columns);
|
||||
const auto topIdx = ptToIdx(topPt, m_img.columns);
|
||||
const auto bottomIdx = ptToIdx(bottomPt, m_img.columns);
|
||||
const auto idx = ptToIdx(pt, m_img.columns());
|
||||
const auto leftIdx = ptToIdx(leftPt, m_img.columns());
|
||||
const auto rightIdx = ptToIdx(rightPt, m_img.columns());
|
||||
const auto topIdx = ptToIdx(topPt, m_img.columns());
|
||||
const auto bottomIdx = ptToIdx(bottomPt, m_img.columns());
|
||||
const auto tile = tileIdx(pt);
|
||||
// mark pixels to update
|
||||
pixels[idx % PixelsPerTile] = true;
|
||||
|
@ -69,31 +69,31 @@ void TileSheetGrid::setBufferObjects(const geo::Vec2 &paneSize, const TileSheet
|
||||
setBufferObject(pt1, pt2, c, vbo, pixSize);
|
||||
};
|
||||
// set buffer length
|
||||
const auto width = img.columns * TileWidth;
|
||||
const auto height = img.rows * TileHeight;
|
||||
const auto width = img.columns() * TileWidth;
|
||||
const auto height = img.rows() * TileHeight;
|
||||
const auto pixelCnt = static_cast<unsigned>(width * height);
|
||||
const auto tileCnt = static_cast<unsigned>(img.columns * img.rows);
|
||||
const auto tileCnt = static_cast<unsigned>(img.columns() * img.rows());
|
||||
m_bufferSet.vertices.resize((tileCnt + pixelCnt) * VertexVboLength);
|
||||
// set buffer
|
||||
auto i = 0ull;
|
||||
// pixel outlines
|
||||
constexpr auto pixOutlineColor = color32(0.4431f, 0.4901f, 0.4941f);
|
||||
for (auto x = 0; x < img.columns * TileWidth + 1; ++x) {
|
||||
set(i, {x, 0}, {x, img.rows * TileHeight}, pixOutlineColor);
|
||||
for (auto x = 0; x < img.columns() * TileWidth + 1; ++x) {
|
||||
set(i, {x, 0}, {x, img.rows() * TileHeight}, pixOutlineColor);
|
||||
++i;
|
||||
}
|
||||
for (auto y = 0; y < img.rows * TileHeight + 1; ++y) {
|
||||
set(i, {0, y}, {img.columns * TileWidth, y}, pixOutlineColor);
|
||||
for (auto y = 0; y < img.rows() * TileHeight + 1; ++y) {
|
||||
set(i, {0, y}, {img.columns() * TileWidth, y}, pixOutlineColor);
|
||||
++i;
|
||||
}
|
||||
// tile outlines
|
||||
constexpr auto tileOutlineColor = color32(0.f, 0.f, 0.f);
|
||||
for (auto x = 0; x < img.columns * TileWidth + 1; x += TileWidth) {
|
||||
set(i, {x, 0}, {x, img.rows * TileHeight}, tileOutlineColor);
|
||||
for (auto x = 0; x < img.columns() * TileWidth + 1; x += TileWidth) {
|
||||
set(i, {x, 0}, {x, img.rows() * TileHeight}, tileOutlineColor);
|
||||
++i;
|
||||
}
|
||||
for (auto y = 0; y < img.rows * TileHeight + 1; y += TileHeight) {
|
||||
set(i, {0, y}, {img.columns * TileWidth, y}, tileOutlineColor);
|
||||
for (auto y = 0; y < img.rows() * TileHeight + 1; y += TileHeight) {
|
||||
set(i, {0, y}, {img.columns() * TileWidth, y}, tileOutlineColor);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ void TileSheetPixels::setPixelBufferObject(const geo::Vec2 &paneSize, unsigned v
|
||||
void TileSheetPixels::setBufferObjects(const geo::Vec2 &paneSize, const TileSheet &img, const Palette &pal, glutils::BufferSet *bg) noexcept {
|
||||
const auto setPixel = [this, paneSize, bg, img, pal](std::size_t i, uint8_t p) {
|
||||
const auto color = pal.colors[p];
|
||||
const auto pt = idxToPt(static_cast<int>(i), img.columns);
|
||||
const auto pt = idxToPt(static_cast<int>(i), img.columns());
|
||||
const auto fx = static_cast<float>(pt.x);
|
||||
const auto fy = static_cast<float>(pt.y);
|
||||
const auto vbo = &bg->vertices[i * VertexVboLength];
|
||||
@ -89,8 +89,8 @@ void TileSheetPixels::setBufferObjects(const geo::Vec2 &paneSize, const TileShee
|
||||
setPixelBufferObject(paneSize, i * VertexVboRows, fx, fy, color, vbo, ebo);
|
||||
};
|
||||
// set buffer lengths
|
||||
const auto width = img.columns * TileWidth;
|
||||
const auto height = img.rows * TileHeight;
|
||||
const auto width = img.columns() * TileWidth;
|
||||
const auto height = img.rows() * TileHeight;
|
||||
const auto tiles = static_cast<unsigned>(width * height);
|
||||
m_bufferSet.vertices.resize(tiles * VertexVboLength);
|
||||
m_bufferSet.elements.resize(tiles * VertexEboLength);
|
||||
|
71
src/nostalgia/core/typeconv.cpp
Normal file
71
src/nostalgia/core/typeconv.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include <ox/std/defines.hpp>
|
||||
|
||||
#ifndef OX_BARE_METAL
|
||||
#include <ox/claw/read.hpp>
|
||||
|
||||
#include "typeconv.hpp"
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
struct Converter {
|
||||
virtual bool matches(const ox::String &srcTypeName, int srcTypeVersion, const ox::String &dstTypeName, int dstTypeVersion) noexcept = 0;
|
||||
|
||||
virtual ~Converter() noexcept = default;
|
||||
|
||||
virtual ox::Error convert(const ox::Buffer &pV1Buff, void *pV2) noexcept = 0;
|
||||
};
|
||||
|
||||
struct TileSheetV1ToV2Converter: public Converter {
|
||||
constexpr TileSheetV1ToV2Converter() noexcept = default;
|
||||
|
||||
virtual ~TileSheetV1ToV2Converter() noexcept = default;
|
||||
|
||||
bool matches(const ox::String &srcTypeName, int srcTypeVersion, const ox::String &dstTypeName, int dstTypeVersion) noexcept final {
|
||||
return srcTypeName == TileSheetV1::TypeName
|
||||
&& srcTypeVersion == TileSheetV1::TypeVersion
|
||||
&& dstTypeName == TileSheet::TypeName
|
||||
&& dstTypeVersion == TileSheet::TypeVersion;
|
||||
}
|
||||
|
||||
ox::Error convert(const ox::Buffer &pV1Buff, void *pV2) noexcept final {
|
||||
oxRequire(v1, ox::readClaw<TileSheetV1>(pV1Buff));
|
||||
auto v2 = static_cast<TileSheet*>(pV2);
|
||||
v2->bpp = v1.bpp;
|
||||
v2->subsheet.name = "Root";
|
||||
v2->subsheet.rows = v1.rows;
|
||||
v2->subsheet.columns = v1.columns;
|
||||
v2->subsheet.size = v1.pixels.size();
|
||||
v2->defaultPalette = v1.defaultPalette;
|
||||
v2->pal = v1.pal;
|
||||
v2->pixels = v1.pixels;
|
||||
return OxError(0);
|
||||
}
|
||||
};
|
||||
|
||||
static const auto converters = [] {
|
||||
ox::Vector<ox::UniquePtr<Converter>, 1> converters;
|
||||
converters.emplace_back(new TileSheetV1ToV2Converter());
|
||||
return converters;
|
||||
}();
|
||||
|
||||
static auto findConverter(const ox::String &srcTypeName, int srcTypeVersion, const ox::String &dstTypeName, int dstTypeVersion) noexcept -> ox::Result<Converter*> {
|
||||
for (auto &c : converters) {
|
||||
if (c->matches(srcTypeName, srcTypeVersion, dstTypeName, dstTypeVersion)) {
|
||||
return c.get();
|
||||
}
|
||||
}
|
||||
return OxError(1, "Could not find converter");
|
||||
};
|
||||
|
||||
ox::Error convert(const ox::Buffer &srcBuffer, const ox::String &dstTypeName, int dstTypeVersion, void *dstObj) noexcept {
|
||||
oxRequire(hdr, ox::readClawHeader(srcBuffer));
|
||||
oxRequire(c, findConverter(hdr.typeName, hdr.typeVersion, dstTypeName, dstTypeVersion));
|
||||
return c->convert(srcBuffer, dstObj);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
17
src/nostalgia/core/typeconv.hpp
Normal file
17
src/nostalgia/core/typeconv.hpp
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ox/std/def.hpp>
|
||||
#include <ox/std/error.hpp>
|
||||
#include <ox/std/string.hpp>
|
||||
|
||||
#include "gfx.hpp"
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
ox::Error convert(const ox::Buffer &srcBuffer, const ox::String &dstTypeName, int dstTypeVersion, void *dstObj) noexcept;
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user