[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
|
NostalgiaCore
|
||||||
gfx.cpp
|
gfx.cpp
|
||||||
media.cpp
|
media.cpp
|
||||||
|
typeconv.cpp
|
||||||
${NOSTALGIA_CORE_IMPL_SRC}
|
${NOSTALGIA_CORE_IMPL_SRC}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -79,6 +80,7 @@ install(
|
|||||||
gfx.hpp
|
gfx.hpp
|
||||||
input.hpp
|
input.hpp
|
||||||
media.hpp
|
media.hpp
|
||||||
|
typeconv.hpp
|
||||||
DESTINATION
|
DESTINATION
|
||||||
include/nostalgia/core
|
include/nostalgia/core
|
||||||
)
|
)
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "gfx.hpp"
|
#include "gfx.hpp"
|
||||||
#include "input.hpp"
|
#include "input.hpp"
|
||||||
#include "media.hpp"
|
#include "media.hpp"
|
||||||
|
#include "typeconv.hpp"
|
||||||
|
|
||||||
namespace nostalgia::core {
|
namespace nostalgia::core {
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ struct Palette {
|
|||||||
ox::Vector<Color16> colors;
|
ox::Vector<Color16> colors;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TileSheet {
|
struct TileSheetV1 {
|
||||||
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.NostalgiaGraphic";
|
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.NostalgiaGraphic";
|
||||||
static constexpr auto TypeVersion = 1;
|
static constexpr auto TypeVersion = 1;
|
||||||
int8_t bpp = 0;
|
int8_t bpp = 0;
|
||||||
@ -48,7 +48,7 @@ struct TileSheet {
|
|||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr uint8_t getPixel4Bpp(std::size_t idx) const noexcept {
|
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) {
|
if (idx & 1) {
|
||||||
return this->pixels[idx / 2] >> 4;
|
return this->pixels[idx / 2] >> 4;
|
||||||
} else {
|
} else {
|
||||||
@ -58,7 +58,7 @@ struct TileSheet {
|
|||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr uint8_t getPixel8Bpp(std::size_t idx) const noexcept {
|
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];
|
return this->pixels[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,14 +73,14 @@ struct TileSheet {
|
|||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr auto getPixel4Bpp(const geo::Point &pt) const noexcept {
|
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);
|
const auto idx = ptToIdx(pt, this->columns);
|
||||||
return getPixel4Bpp(idx);
|
return getPixel4Bpp(idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr auto getPixel8Bpp(const geo::Point &pt) const noexcept {
|
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);
|
const auto idx = ptToIdx(pt, this->columns);
|
||||||
return getPixel8Bpp(idx);
|
return getPixel8Bpp(idx);
|
||||||
}
|
}
|
||||||
@ -92,7 +92,7 @@ struct TileSheet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constexpr void setPixel(uint64_t idx, uint8_t palIdx) noexcept {
|
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 (bpp == 4) {
|
||||||
if (idx & 1) {
|
if (idx & 1) {
|
||||||
pixel = (pixel & 0b0000'1111) | (palIdx << 4);
|
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)
|
oxModelBegin(Palette)
|
||||||
oxModelField(colors)
|
oxModelField(colors)
|
||||||
oxModelEnd()
|
oxModelEnd()
|
||||||
|
|
||||||
oxModelBegin(TileSheet)
|
oxModelBegin(TileSheetV1)
|
||||||
oxModelField(bpp)
|
oxModelField(bpp)
|
||||||
oxModelField(rows)
|
oxModelField(rows)
|
||||||
oxModelField(columns)
|
oxModelField(columns)
|
||||||
@ -123,6 +256,23 @@ oxModelBegin(TileSheet)
|
|||||||
oxModelField(pixels)
|
oxModelField(pixels)
|
||||||
oxModelEnd()
|
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 {
|
struct Sprite {
|
||||||
unsigned idx = 0;
|
unsigned idx = 0;
|
||||||
unsigned x = 0;
|
unsigned x = 0;
|
||||||
|
@ -4,27 +4,40 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <ox/std/defines.hpp>
|
||||||
|
|
||||||
#include <ox/claw/claw.hpp>
|
#include <ox/claw/claw.hpp>
|
||||||
#include <ox/fs/fs.hpp>
|
#include <ox/fs/fs.hpp>
|
||||||
|
|
||||||
#include "context.hpp"
|
#include "context.hpp"
|
||||||
|
#include "typeconv.hpp"
|
||||||
|
|
||||||
namespace nostalgia::core {
|
namespace nostalgia::core {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ox::Result<AssetRef<T>> readObj(Context *ctx, const ox::FileAddress &file, bool forceLoad = false) noexcept {
|
ox::Result<AssetRef<T>> readObj(Context *ctx, const ox::FileAddress &file, bool forceLoad = false) noexcept {
|
||||||
#ifndef OX_BARE_METAL
|
#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());
|
oxRequire(path, file.getPath());
|
||||||
if (forceLoad) {
|
if (forceLoad) {
|
||||||
oxRequire(buff, ctx->rom->read(file));
|
oxRequire(buff, ctx->rom->read(file));
|
||||||
oxRequire(obj, ox::readClaw<T>(buff));
|
oxRequire(obj, readConvert(buff));
|
||||||
oxRequire(cached, ctx->assetManager.template setAsset(path, obj));
|
oxRequire(cached, ctx->assetManager.template setAsset(path, obj));
|
||||||
return cached;
|
return cached;
|
||||||
} else {
|
} else {
|
||||||
auto [cached, err] = ctx->assetManager.template getAsset<T>(path);
|
auto [cached, err] = ctx->assetManager.template getAsset<T>(path);
|
||||||
if (err) {
|
if (err) {
|
||||||
oxRequire(buff, ctx->rom->read(file));
|
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));
|
oxReturnError(ctx->assetManager.template setAsset(path, obj).moveTo(&cached));
|
||||||
}
|
}
|
||||||
return cached;
|
return cached;
|
||||||
|
@ -47,7 +47,7 @@ class TileSheetEditorImGui: public studio::Editor {
|
|||||||
|
|
||||||
void draw(core::Context*) noexcept override;
|
void draw(core::Context*) noexcept override;
|
||||||
|
|
||||||
virtual studio::UndoStack *undoStack() noexcept override;
|
studio::UndoStack *undoStack() noexcept final;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void saveItem() override;
|
void saveItem() override;
|
||||||
|
@ -40,8 +40,8 @@ void TileSheetEditor::draw() noexcept {
|
|||||||
|
|
||||||
void TileSheetEditor::scrollV(const geo::Vec2 &paneSz, float wheel, bool zoomMod) noexcept {
|
void TileSheetEditor::scrollV(const geo::Vec2 &paneSz, float wheel, bool zoomMod) noexcept {
|
||||||
const auto pixelSize = m_pixelsDrawer.pixelSize(paneSz);
|
const auto pixelSize = m_pixelsDrawer.pixelSize(paneSz);
|
||||||
const ImVec2 sheetSize(pixelSize.x * static_cast<float>(img().columns) * TileWidth,
|
const ImVec2 sheetSize(pixelSize.x * static_cast<float>(img().columns()) * TileWidth,
|
||||||
pixelSize.y * static_cast<float>(img().rows) * TileHeight);
|
pixelSize.y * static_cast<float>(img().rows()) * TileHeight);
|
||||||
if (zoomMod) {
|
if (zoomMod) {
|
||||||
m_pixelSizeMod = ox::clamp(m_pixelSizeMod + wheel * 0.02f, 0.55f, 2.f);
|
m_pixelSizeMod = ox::clamp(m_pixelSizeMod + wheel * 0.02f, 0.55f, 2.f);
|
||||||
m_pixelsDrawer.setPixelSizeMod(m_pixelSizeMod);
|
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 {
|
void TileSheetEditor::scrollH(const geo::Vec2 &paneSz, float wheelh) noexcept {
|
||||||
const auto pixelSize = m_pixelsDrawer.pixelSize(paneSz);
|
const auto pixelSize = m_pixelsDrawer.pixelSize(paneSz);
|
||||||
const ImVec2 sheetSize(pixelSize.x * static_cast<float>(img().columns) * TileWidth,
|
const ImVec2 sheetSize(pixelSize.x * static_cast<float>(img().columns()) * TileWidth,
|
||||||
pixelSize.y * static_cast<float>(img().rows) * TileHeight);
|
pixelSize.y * static_cast<float>(img().rows()) * TileHeight);
|
||||||
m_scrollOffset.x += wheelh * 0.1f;
|
m_scrollOffset.x += wheelh * 0.1f;
|
||||||
m_scrollOffset.x = ox::clamp(m_scrollOffset.x, -(sheetSize.x / 2), 0.f);
|
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 {
|
void TileSheetEditorModel::drawCommand(const geo::Point &pt, std::size_t palIdx) noexcept {
|
||||||
if (m_ongoingDrawCommand) {
|
if (m_ongoingDrawCommand) {
|
||||||
m_updated = m_ongoingDrawCommand->append(ptToIdx(pt, m_img.columns));
|
m_updated = m_ongoingDrawCommand->append(ptToIdx(pt, m_img.columns()));
|
||||||
} else {
|
} else {
|
||||||
const auto idx = ptToIdx(pt, m_img.columns);
|
const auto idx = ptToIdx(pt, m_img.columns());
|
||||||
if (m_img.getPixel(idx) != palIdx) {
|
if (m_img.getPixel(idx) != palIdx) {
|
||||||
pushCommand(new DrawCommand(&m_updated, &m_img, 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 {
|
void TileSheetEditorModel::getFillPixels(bool *pixels, const geo::Point &pt, int oldColor) const noexcept {
|
||||||
const auto tileIdx = [this](const geo::Point &pt) noexcept {
|
const auto tileIdx = [this](const geo::Point &pt) noexcept {
|
||||||
return ptToIdx(pt, img().columns) / PixelsPerTile;
|
return ptToIdx(pt, img().columns()) / PixelsPerTile;
|
||||||
};
|
};
|
||||||
// get points
|
// get points
|
||||||
const auto leftPt = pt + geo::Point(-1, 0);
|
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 topPt = pt + geo::Point(0, -1);
|
||||||
const auto bottomPt = pt + geo::Point(0, 1);
|
const auto bottomPt = pt + geo::Point(0, 1);
|
||||||
// calculate indices
|
// calculate indices
|
||||||
const auto idx = ptToIdx(pt, m_img.columns);
|
const auto idx = ptToIdx(pt, m_img.columns());
|
||||||
const auto leftIdx = ptToIdx(leftPt, m_img.columns);
|
const auto leftIdx = ptToIdx(leftPt, m_img.columns());
|
||||||
const auto rightIdx = ptToIdx(rightPt, m_img.columns);
|
const auto rightIdx = ptToIdx(rightPt, m_img.columns());
|
||||||
const auto topIdx = ptToIdx(topPt, m_img.columns);
|
const auto topIdx = ptToIdx(topPt, m_img.columns());
|
||||||
const auto bottomIdx = ptToIdx(bottomPt, m_img.columns);
|
const auto bottomIdx = ptToIdx(bottomPt, m_img.columns());
|
||||||
const auto tile = tileIdx(pt);
|
const auto tile = tileIdx(pt);
|
||||||
// mark pixels to update
|
// mark pixels to update
|
||||||
pixels[idx % PixelsPerTile] = true;
|
pixels[idx % PixelsPerTile] = true;
|
||||||
|
@ -69,31 +69,31 @@ void TileSheetGrid::setBufferObjects(const geo::Vec2 &paneSize, const TileSheet
|
|||||||
setBufferObject(pt1, pt2, c, vbo, pixSize);
|
setBufferObject(pt1, pt2, c, vbo, pixSize);
|
||||||
};
|
};
|
||||||
// set buffer length
|
// set buffer length
|
||||||
const auto width = img.columns * TileWidth;
|
const auto width = img.columns() * TileWidth;
|
||||||
const auto height = img.rows * TileHeight;
|
const auto height = img.rows() * TileHeight;
|
||||||
const auto pixelCnt = static_cast<unsigned>(width * height);
|
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);
|
m_bufferSet.vertices.resize((tileCnt + pixelCnt) * VertexVboLength);
|
||||||
// set buffer
|
// set buffer
|
||||||
auto i = 0ull;
|
auto i = 0ull;
|
||||||
// pixel outlines
|
// pixel outlines
|
||||||
constexpr auto pixOutlineColor = color32(0.4431f, 0.4901f, 0.4941f);
|
constexpr auto pixOutlineColor = color32(0.4431f, 0.4901f, 0.4941f);
|
||||||
for (auto x = 0; x < img.columns * TileWidth + 1; ++x) {
|
for (auto x = 0; x < img.columns() * TileWidth + 1; ++x) {
|
||||||
set(i, {x, 0}, {x, img.rows * TileHeight}, pixOutlineColor);
|
set(i, {x, 0}, {x, img.rows() * TileHeight}, pixOutlineColor);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
for (auto y = 0; y < img.rows * TileHeight + 1; ++y) {
|
for (auto y = 0; y < img.rows() * TileHeight + 1; ++y) {
|
||||||
set(i, {0, y}, {img.columns * TileWidth, y}, pixOutlineColor);
|
set(i, {0, y}, {img.columns() * TileWidth, y}, pixOutlineColor);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
// tile outlines
|
// tile outlines
|
||||||
constexpr auto tileOutlineColor = color32(0.f, 0.f, 0.f);
|
constexpr auto tileOutlineColor = color32(0.f, 0.f, 0.f);
|
||||||
for (auto x = 0; x < img.columns * TileWidth + 1; x += TileWidth) {
|
for (auto x = 0; x < img.columns() * TileWidth + 1; x += TileWidth) {
|
||||||
set(i, {x, 0}, {x, img.rows * TileHeight}, tileOutlineColor);
|
set(i, {x, 0}, {x, img.rows() * TileHeight}, tileOutlineColor);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
for (auto y = 0; y < img.rows * TileHeight + 1; y += TileHeight) {
|
for (auto y = 0; y < img.rows() * TileHeight + 1; y += TileHeight) {
|
||||||
set(i, {0, y}, {img.columns * TileWidth, y}, tileOutlineColor);
|
set(i, {0, y}, {img.columns() * TileWidth, y}, tileOutlineColor);
|
||||||
++i;
|
++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 {
|
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 setPixel = [this, paneSize, bg, img, pal](std::size_t i, uint8_t p) {
|
||||||
const auto color = pal.colors[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 fx = static_cast<float>(pt.x);
|
||||||
const auto fy = static_cast<float>(pt.y);
|
const auto fy = static_cast<float>(pt.y);
|
||||||
const auto vbo = &bg->vertices[i * VertexVboLength];
|
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);
|
setPixelBufferObject(paneSize, i * VertexVboRows, fx, fy, color, vbo, ebo);
|
||||||
};
|
};
|
||||||
// set buffer lengths
|
// set buffer lengths
|
||||||
const auto width = img.columns * TileWidth;
|
const auto width = img.columns() * TileWidth;
|
||||||
const auto height = img.rows * TileHeight;
|
const auto height = img.rows() * TileHeight;
|
||||||
const auto tiles = static_cast<unsigned>(width * height);
|
const auto tiles = static_cast<unsigned>(width * height);
|
||||||
m_bufferSet.vertices.resize(tiles * VertexVboLength);
|
m_bufferSet.vertices.resize(tiles * VertexVboLength);
|
||||||
m_bufferSet.elements.resize(tiles * VertexEboLength);
|
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