[nostalgia] Fill out basic Scene system functionality

This commit is contained in:
Gary Talent 2023-02-07 23:17:58 -06:00
parent eb55144211
commit 8077aaf0ae
34 changed files with 1111 additions and 631 deletions

View File

@ -0,0 +1,4 @@
O1;net.drinkingtea.ox.TypeDescriptor;1;{
"primitiveType" : 2,
"typeName" : "B.bool"
}

View File

@ -0,0 +1,42 @@
O1;net.drinkingtea.ox.TypeDescriptor;1;{
"fieldList" :
[
{
"fieldName" : "name",
"typeId" : "net.drinkingtea.ox.BasicString#8#;1"
},
{
"fieldName" : "rows",
"typeId" : "B.int32;0"
},
{
"fieldName" : "columns",
"typeId" : "B.int32;0"
},
{
"fieldName" : "subsheets",
"subscriptLevels" : 1,
"subscriptStack" :
[
{
"subscriptType" : 4
}
],
"typeId" : "net.drinkingtea.nostalgia.core.TileSheet.SubSheet;3"
},
{
"fieldName" : "pixels",
"subscriptLevels" : 1,
"subscriptStack" :
[
{
"subscriptType" : 4
}
],
"typeId" : "B.uint8;0"
}
],
"primitiveType" : 5,
"typeName" : "net.drinkingtea.nostalgia.core.TileSheet.SubSheet",
"typeVersion" : 3
}

View File

@ -0,0 +1,24 @@
O1;net.drinkingtea.ox.TypeDescriptor;1;{
"fieldList" :
[
{
"fieldName" : "bpp",
"typeId" : "B.int8;0"
},
{
"fieldName" : "idIt",
"typeId" : "B.int32;0"
},
{
"fieldName" : "defaultPalette",
"typeId" : "net.drinkingtea.ox.FileAddress;1"
},
{
"fieldName" : "subsheet",
"typeId" : "net.drinkingtea.nostalgia.core.TileSheet.SubSheet;3"
}
],
"primitiveType" : 5,
"typeName" : "net.drinkingtea.nostalgia.core.TileSheet",
"typeVersion" : 3
}

View File

@ -14,6 +14,7 @@ O1;net.drinkingtea.ox.TypeDescriptor;1;{
"typeId" : "B.uint64;0" "typeId" : "B.uint64;0"
} }
], ],
"preloadable" : true,
"primitiveType" : 6, "primitiveType" : 6,
"typeName" : "net.drinkingtea.ox.FileAddress.Data", "typeName" : "net.drinkingtea.ox.FileAddress.Data",
"typeVersion" : 1 "typeVersion" : 1

View File

@ -10,6 +10,7 @@ O1;net.drinkingtea.ox.TypeDescriptor;1;{
"typeId" : "net.drinkingtea.ox.FileAddress.Data" "typeId" : "net.drinkingtea.ox.FileAddress.Data"
} }
], ],
"preloadable" : true,
"primitiveType" : 5, "primitiveType" : 5,
"typeName" : "net.drinkingtea.ox.FileAddress", "typeName" : "net.drinkingtea.ox.FileAddress",
"typeVersion" : 1 "typeVersion" : 1

View File

@ -0,0 +1 @@
M2;net.drinkingtea.nostalgia.core.Palette;1;ûÿ³Ö

Binary file not shown.

Binary file not shown.

View File

@ -2,6 +2,8 @@ add_library(
NostalgiaCore-Common OBJECT NostalgiaCore-Common OBJECT
gfx.cpp gfx.cpp
module.cpp module.cpp
tilesheet.cpp
typeconv.cpp
typestore.cpp typestore.cpp
) )

View File

@ -14,6 +14,7 @@
#include "color.hpp" #include "color.hpp"
#include "context.hpp" #include "context.hpp"
#include "ptidxconv.hpp" #include "ptidxconv.hpp"
#include "tilesheet.hpp"
namespace nostalgia::core { namespace nostalgia::core {
@ -31,431 +32,6 @@ enum class TileSheetSpace {
Sprite Sprite
}; };
struct NostalgiaPalette {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.NostalgiaPalette";
static constexpr auto TypeVersion = 1;
ox::Vector<Color16> colors = {};
};
struct Palette {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.Palette";
static constexpr auto TypeVersion = 1;
ox::Vector<Color16> colors = {};
[[nodiscard]]
constexpr Color16 color(auto idx) const noexcept {
if (idx < colors.size()) [[likely]] {
return colors[idx];
}
return 0;
}
};
// Predecessor to TileSheet, kept for backward compatibility
struct NostalgiaGraphic {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.NostalgiaGraphic";
static constexpr auto TypeVersion = 1;
int8_t bpp = 0;
// rows and columns are really only used by TileSheetEditor
int rows = 1;
int columns = 1;
ox::FileAddress defaultPalette;
Palette pal;
ox::Vector<uint8_t> pixels = {};
};
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 = 1;
ox::String name;
int columns = 0;
int rows = 0;
ox::Vector<SubSheet> subsheets;
ox::Vector<uint8_t> pixels;
constexpr SubSheet() noexcept = default;
constexpr SubSheet(const SubSheet &other) noexcept {
name = other.name;
columns = other.columns;
rows = other.rows;
subsheets = other.subsheets;
pixels = other.pixels;
}
constexpr SubSheet(SubSheet &&other) noexcept {
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(ox::CRStringView pName, int pColumns, int pRows, int bpp) noexcept:
name(pName), columns(pColumns), rows(pRows),
pixels(static_cast<std::size_t>(columns * rows * PixelsPerTile) / (bpp == 4 ? 2u : 1u)) {
}
constexpr SubSheet(ox::CRStringView pName, int pColumns, int pRows, ox::Vector<uint8_t> pPixels) noexcept:
name(pName), columns(pColumns), rows(pRows), pixels(std::move(pPixels)) {
}
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;
}
[[nodiscard]]
constexpr auto idx(const geo::Point &pt) const noexcept {
return ptToIdx(pt, columns);
}
/**
* Reads all pixels of this sheet or its children into the given pixel list
* @param pixels
*/
constexpr void readPixelsTo(ox::Vector<uint8_t> *pPixels, int8_t bpp) const noexcept {
if (subsheets.size()) {
for (auto &s: subsheets) {
s.readPixelsTo(pPixels);
}
} else {
if (bpp == 4) {
for (auto p: this->pixels) {
pPixels->emplace_back(p & 0b1111);
pPixels->emplace_back(p >> 4);
}
} else {
for (auto p: this->pixels) {
pPixels->emplace_back(p);
}
}
}
}
/**
* Reads all pixels of this sheet or its children into the given pixel list
* @param pixels
*/
constexpr void readPixelsTo(ox::Vector<uint8_t> *pPixels) const noexcept {
if (subsheets.size()) {
for (auto &s: subsheets) {
s.readPixelsTo(pPixels);
}
} else {
for (auto p : this->pixels) {
pPixels->emplace_back(p);
}
}
}
[[nodiscard]]
constexpr std::size_t size() const noexcept {
return static_cast<std::size_t>(columns) * static_cast<std::size_t>(rows);
}
[[nodiscard]]
constexpr std::size_t unusedPixels() const noexcept {
std::size_t childrenSize = 0;
for (auto &c : subsheets) {
childrenSize += c.size();
}
return size() - childrenSize;
}
[[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;
}
}
[[nodiscard]]
constexpr uint8_t getPixel8Bpp(std::size_t idx) const noexcept {
return this->pixels[idx];
}
[[nodiscard]]
constexpr auto getPixel(int8_t pBpp, std::size_t idx) const noexcept {
if (pBpp == 4) {
return getPixel4Bpp(idx);
} else {
return getPixel8Bpp(idx);
}
}
[[nodiscard]]
constexpr auto getPixel4Bpp(const geo::Point &pt) const noexcept {
const auto idx = ptToIdx(pt, columns);
return getPixel4Bpp(idx);
}
[[nodiscard]]
constexpr auto getPixel8Bpp(const geo::Point &pt) const noexcept {
const auto idx = ptToIdx(pt, columns);
return getPixel8Bpp(idx);
}
[[nodiscard]]
constexpr auto getPixel(int8_t pBpp, const geo::Point &pt) const noexcept {
const auto idx = ptToIdx(pt, columns);
return getPixel(pBpp, idx);
}
constexpr auto walkPixels(int8_t pBpp, auto callback) const noexcept {
if (pBpp == 4) {
const auto pixelCnt = ox::min<std::size_t>(static_cast<std::size_t>(columns * rows * PixelsPerTile) / 2,
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 = pixels[i] & 0xF;
const auto colorIdx2 = pixels[i] >> 4;
callback(i * 2 + 0, colorIdx1);
callback(i * 2 + 1, colorIdx2);
}
} else {
const auto pixelCnt = ox::min<std::size_t>(static_cast<std::size_t>(columns * rows * PixelsPerTile),
pixels.size());
for (std::size_t i = 0; i < pixelCnt; ++i) {
const auto p = pixels[i];
callback(i, p);
}
}
}
constexpr void setPixel(int8_t pBpp, uint64_t idx, uint8_t palIdx) noexcept {
auto &pixel = this->pixels[idx / 2];
if (pBpp == 4) {
if (idx & 1) {
pixel = (pixel & 0b0000'1111) | (palIdx << 4);
} else {
pixel = (pixel & 0b1111'0000) | (palIdx);
}
} else {
pixel = palIdx;
}
}
constexpr void setPixel(int8_t pBpp, const geo::Point &pt, uint8_t palIdx) noexcept {
const auto idx = ptToIdx(pt, columns);
setPixel(pBpp, idx, palIdx);
}
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");
}
}
/**
* 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]]
constexpr auto pixelCnt(int8_t pBpp) const noexcept {
return pBpp == 4 ? pixels.size() * 2 : pixels.size();
}
};
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.TileSheet";
static constexpr auto TypeVersion = 2;
int8_t bpp = 4;
ox::FileAddress defaultPalette;
SubSheet subsheet{"Root", 1, 1, bpp};
constexpr TileSheet() noexcept = default;
TileSheet(const TileSheet &other) noexcept = default;
inline TileSheet(TileSheet &&other) noexcept:
bpp(other.bpp),
defaultPalette(std::move(other.defaultPalette)),
subsheet(std::move(other.subsheet)) {
}
inline auto &operator=(const TileSheet &other) noexcept {
if (this != &other) {
bpp = other.bpp;
defaultPalette = other.defaultPalette;
subsheet = other.subsheet; } return *this;
}
inline auto &operator=(TileSheet &&other) noexcept {
bpp = other.bpp;
defaultPalette = std::move(other.defaultPalette);
subsheet = std::move(other.subsheet);
return *this;
}
[[nodiscard]]
constexpr auto 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.size()) {
out.back().value = pSubsheet->subsheets.size() - 1;
} else {
out.pop_back();
}
return out;
}
return validateSubSheetIdx(pIdx, pIdxIt + 1, &pSubsheet->subsheets[pIdx[pIdxIt]]);
}
/**
* validateSubSheetIdx takes a SubSheetIdx and moves the index to the
* preceding or parent sheet if the current corresponding sheet does
* not exist.
* @param idx SubSheetIdx to validate and correct
* @return a valid version of idx
*/
[[nodiscard]]
constexpr auto validateSubSheetIdx(const SubSheetIdx &idx) noexcept {
return validateSubSheetIdx(idx, 0, &subsheet);
}
[[nodiscard]]
constexpr static const auto &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]);
}
[[nodiscard]]
constexpr static auto &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]]);
}
[[nodiscard]]
constexpr const auto &getSubSheet(const SubSheetIdx &idx) const noexcept {
return getSubSheet(idx, 0, &subsheet);
}
[[nodiscard]]
constexpr auto &getSubSheet(const SubSheetIdx &idx) noexcept {
return getSubSheet(idx, 0, &subsheet);
}
constexpr ox::Error addSubSheet(const SubSheetIdx &idx) noexcept {
auto &parent = getSubSheet(idx);
if (parent.subsheets.size() < 2) {
parent.subsheets.emplace_back(ox::sfmt("Subsheet {}", parent.subsheets.size()), 1, 1, bpp);
} else {
parent.subsheets.emplace_back("Subsheet 0", parent.columns, parent.rows, bpp);
parent.subsheets.emplace_back("Subsheet 1", 1, 1, bpp);
}
return OxError(0);
}
[[nodiscard]]
constexpr static auto 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]]);
}
[[nodiscard]]
constexpr auto rmSubSheet(const SubSheetIdx &idx) noexcept {
return rmSubSheet(idx, 0, &subsheet);
}
[[nodiscard]]
constexpr auto getPixel4Bpp(const geo::Point &pt, const SubSheetIdx &subsheetIdx) const noexcept {
oxAssert(bpp == 4, "TileSheetV1::getPixel4Bpp: wrong bpp");
auto &s = this->getSubSheet(subsheetIdx);
const auto idx = ptToIdx(pt, s.columns);
return s.getPixel4Bpp(idx);
}
[[nodiscard]]
constexpr auto getPixel8Bpp(const geo::Point &pt, const SubSheetIdx &subsheetIdx) const noexcept {
oxAssert(bpp == 8, "TileSheetV1::getPixel8Bpp: wrong bpp");
auto &s = this->getSubSheet(subsheetIdx);
const auto idx = ptToIdx(pt, s.columns);
return s.getPixel8Bpp(idx);
}
[[nodiscard]]
auto pixels() const noexcept {
ox::Vector<uint8_t> out;
subsheet.readPixelsTo(&out);
return out;
}
};
struct CompactTileSheet {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.CompactTileSheet";
static constexpr auto TypeVersion = 1;
int8_t bpp = 0;
ox::FileAddress defaultPalette;
ox::Vector<uint8_t> pixels = {};
};
oxModelBegin(NostalgiaPalette)
oxModelField(colors)
oxModelEnd()
oxModelBegin(Palette)
oxModelField(colors)
oxModelEnd()
oxModelBegin(NostalgiaGraphic)
oxModelField(bpp)
oxModelField(rows)
oxModelField(columns)
oxModelField(defaultPalette)
oxModelField(pal)
oxModelField(pixels)
oxModelEnd()
oxModelBegin(TileSheet::SubSheet)
oxModelField(name);
oxModelField(rows);
oxModelField(columns);
oxModelField(subsheets)
oxModelField(pixels)
oxModelEnd()
oxModelBegin(TileSheet)
oxModelField(bpp)
oxModelField(defaultPalette)
oxModelField(subsheet)
oxModelEnd()
oxModelBegin(CompactTileSheet)
oxModelField(bpp)
oxModelField(defaultPalette)
oxModelField(pixels)
oxModelEnd()
struct Sprite { struct Sprite {
unsigned idx = 0; unsigned idx = 0;
int x = 0; int x = 0;

View File

@ -15,11 +15,12 @@ namespace nostalgia::core {
CoreModule CoreModule::mod; CoreModule CoreModule::mod;
ox::Vector<foundation::BaseConverter*> CoreModule::converters() const noexcept { ox::Vector<const foundation::BaseConverter*> CoreModule::converters() const noexcept {
return { return {
&nostalgiaPaletteToPaletteConverter, &nostalgiaPaletteToPaletteConverter,
&nostalgiaGraphicToTileSheetConverter, &nostalgiaGraphicToTileSheetConverter,
&tileSheetToCompactTileSheetConverter, &tileSheetToCompactTileSheetConverter,
&tileSheetV2ToTileSheetConverter,
}; };
} }
@ -28,9 +29,10 @@ ox::Vector<foundation::PackTransform> CoreModule::packTransforms() const noexcep
// convert tilesheets to CompactTileSheets // convert tilesheets to CompactTileSheets
[](foundation::Context *ctx, ox::Buffer *buff) -> ox::Error { [](foundation::Context *ctx, ox::Buffer *buff) -> ox::Error {
oxRequire(hdr, ox::readClawHeader(*buff)); oxRequire(hdr, ox::readClawHeader(*buff));
const auto typeId = ox::buildTypeId(hdr.typeName, hdr.typeVersion); const auto typeId = ox::buildTypeId(hdr.typeName, hdr.typeVersion, hdr.typeParams);
if (typeId == ox::buildTypeId<TileSheet>() || if (typeId == ox::buildTypeId<TileSheetV1>() ||
typeId == ox::buildTypeId<NostalgiaGraphic>()) { typeId == ox::buildTypeId<TileSheetV2>() ||
typeId == ox::buildTypeId<TileSheet>()) {
oxReturnError(foundation::convertBuffToBuff<core::CompactTileSheet>(ctx, *buff, ox::ClawFormat::Metal).moveTo(buff)); oxReturnError(foundation::convertBuffToBuff<core::CompactTileSheet>(ctx, *buff, ox::ClawFormat::Metal).moveTo(buff));
} }
return {}; return {};

View File

@ -12,14 +12,15 @@ namespace nostalgia::core {
class CoreModule: public foundation::Module { class CoreModule: public foundation::Module {
private: private:
mutable NostalgiaPaletteToPaletteConverter nostalgiaPaletteToPaletteConverter; NostalgiaPaletteToPaletteConverter nostalgiaPaletteToPaletteConverter;
mutable NostalgiaGraphicToTileSheetConverter nostalgiaGraphicToTileSheetConverter; TileSheetV1ToTileSheetConverter nostalgiaGraphicToTileSheetConverter;
mutable TileSheetToCompactTileSheetConverter tileSheetToCompactTileSheetConverter; TileSheetToCompactTileSheetConverter tileSheetToCompactTileSheetConverter;
TileSheetV2ToTileSheetConverter tileSheetV2ToTileSheetConverter;
public: public:
static CoreModule mod; static CoreModule mod;
[[nodiscard]] [[nodiscard]]
ox::Vector<foundation::BaseConverter*> converters() const noexcept override; ox::Vector<const foundation::BaseConverter*> converters() const noexcept override;
[[nodiscard]] [[nodiscard]]
ox::Vector<foundation::PackTransform> packTransforms() const noexcept override; ox::Vector<foundation::PackTransform> packTransforms() const noexcept override;
}; };

View File

@ -0,0 +1,47 @@
/*
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/
#pragma once
#include <ox/std/array.hpp>
#include <ox/std/types.hpp>
#include <ox/model/def.hpp>
#include <nostalgia/geo/point.hpp>
#include <nostalgia/geo/size.hpp>
#include "color.hpp"
#include "context.hpp"
#include "ptidxconv.hpp"
namespace nostalgia::core {
struct NostalgiaPalette {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.NostalgiaPalette";
static constexpr auto TypeVersion = 1;
ox::Vector<Color16> colors = {};
};
struct Palette {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.Palette";
static constexpr auto TypeVersion = 1;
ox::Vector<Color16> colors = {};
[[nodiscard]]
constexpr Color16 color(auto idx) const noexcept {
if (idx < colors.size()) [[likely]] {
return colors[idx];
}
return 0;
}
};
oxModelBegin(NostalgiaPalette)
oxModelField(colors)
oxModelEnd()
oxModelBegin(Palette)
oxModelField(colors)
oxModelEnd()
}

View File

@ -256,12 +256,12 @@ class AddSubSheetCommand: public TileSheetCommand {
auto &parent = m_img->getSubSheet(m_parentIdx); auto &parent = m_img->getSubSheet(m_parentIdx);
if (m_addedSheets.size() < 2) { if (m_addedSheets.size() < 2) {
auto i = parent.subsheets.size(); auto i = parent.subsheets.size();
parent.subsheets.emplace_back(ox::sfmt("Subsheet {}", i), 1, 1, m_img->bpp); parent.subsheets.emplace_back(m_img->idIt++, ox::sfmt("Subsheet {}", i), 1, 1, m_img->bpp);
} else { } else {
parent.subsheets.emplace_back("Subsheet 0", parent.columns, parent.rows, std::move(parent.pixels)); parent.subsheets.emplace_back(m_img->idIt++, "Subsheet 0", parent.columns, parent.rows, std::move(parent.pixels));
parent.rows = 0; parent.rows = 0;
parent.columns = 0; parent.columns = 0;
parent.subsheets.emplace_back("Subsheet 1", 1, 1, m_img->bpp); parent.subsheets.emplace_back(m_img->idIt++, "Subsheet 1", 1, 1, m_img->bpp);
} }
} }

View File

@ -0,0 +1,9 @@
/*
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/
#include "tilesheet.hpp"
namespace nostalgia::core {
}

View File

@ -0,0 +1,566 @@
/*
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/
#pragma once
#include <ox/std/array.hpp>
#include <ox/std/types.hpp>
#include <ox/model/def.hpp>
#include <nostalgia/geo/point.hpp>
#include <nostalgia/geo/size.hpp>
#include "color.hpp"
#include "context.hpp"
#include "ptidxconv.hpp"
#include "palette.hpp"
namespace nostalgia::core {
// Predecessor to TileSheet, kept for backward compatibility
struct TileSheetV1 {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.NostalgiaGraphic";
static constexpr auto TypeVersion = 1;
int8_t bpp = 0;
// rows and columns are really only used by TileSheetEditor
int rows = 1;
int columns = 1;
ox::FileAddress defaultPalette;
Palette pal;
ox::Vector<uint8_t> pixels = {};
};
struct TileSheetV2 {
using SubSheetIdx = ox::Vector<std::size_t, 4>;
struct SubSheet {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.TileSheet.SubSheet";
static constexpr auto TypeVersion = 1;
ox::String name;
int columns = 0;
int rows = 0;
ox::Vector<SubSheet> subsheets;
ox::Vector<uint8_t> pixels;
constexpr SubSheet() noexcept = default;
constexpr SubSheet(ox::CRStringView pName, int pColumns, int pRows, int bpp) noexcept:
name(pName), columns(pColumns), rows(pRows),
pixels(static_cast<std::size_t>(columns * rows * PixelsPerTile) / (bpp == 4 ? 2u : 1u)) {
}
};
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.TileSheet";
static constexpr auto TypeVersion = 2;
int8_t bpp = 4;
ox::FileAddress defaultPalette;
SubSheet subsheet{"Root", 1, 1, bpp};
};
using SubSheetId = int32_t;
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 = 3;
SubSheetId id = 0;
ox::String name;
int columns = 0;
int rows = 0;
ox::Vector<SubSheet> subsheets;
ox::Vector<uint8_t> 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(
SubSheetId pId,
ox::CRStringView pName,
int pColumns,
int pRows,
int bpp) noexcept:
id(pId), name(pName), columns(pColumns), rows(pRows),
pixels(static_cast<std::size_t>(columns * rows * PixelsPerTile) / (bpp == 4 ? 2u : 1u)) {
}
constexpr SubSheet(
SubSheetId pId,
ox::CRStringView pName,
int pColumns,
int pRows,
ox::Vector<uint8_t> pPixels) noexcept:
id(pId), name(pName), columns(pColumns), rows(pRows), pixels(std::move(pPixels)) {
}
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;
}
[[nodiscard]]
constexpr auto idx(const geo::Point &pt) const noexcept {
return ptToIdx(pt, columns);
}
/**
* Reads all pixels of this sheet or its children into the given pixel list
* @param pixels
*/
constexpr void readPixelsTo(ox::Vector<uint8_t> *pPixels, int8_t bpp) const noexcept {
if (subsheets.size()) {
for (auto &s: subsheets) {
s.readPixelsTo(pPixels);
}
} else {
if (bpp == 4) {
for (auto p: this->pixels) {
pPixels->emplace_back(p & 0b1111);
pPixels->emplace_back(p >> 4);
}
} else {
for (auto p: this->pixels) {
pPixels->emplace_back(p);
}
}
}
}
/**
* Reads all pixels of this sheet or its children into the given pixel list
* @param pixels
*/
constexpr void readPixelsTo(ox::Vector<uint8_t> *pPixels) const noexcept {
if (subsheets.size()) {
for (auto &s: subsheets) {
s.readPixelsTo(pPixels);
}
} else {
for (auto p : this->pixels) {
pPixels->emplace_back(p);
}
}
}
[[nodiscard]]
constexpr std::size_t size() const noexcept {
return static_cast<std::size_t>(columns) * static_cast<std::size_t>(rows);
}
[[nodiscard]]
constexpr std::size_t unusedPixels() const noexcept {
std::size_t childrenSize = 0;
for (auto &c : subsheets) {
childrenSize += c.size();
}
return size() - childrenSize;
}
[[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;
}
}
[[nodiscard]]
constexpr uint8_t getPixel8Bpp(std::size_t idx) const noexcept {
return this->pixels[idx];
}
[[nodiscard]]
constexpr auto getPixel(int8_t pBpp, std::size_t idx) const noexcept {
if (pBpp == 4) {
return getPixel4Bpp(idx);
} else {
return getPixel8Bpp(idx);
}
}
[[nodiscard]]
constexpr auto getPixel4Bpp(const geo::Point &pt) const noexcept {
const auto idx = ptToIdx(pt, columns);
return getPixel4Bpp(idx);
}
[[nodiscard]]
constexpr auto getPixel8Bpp(const geo::Point &pt) const noexcept {
const auto idx = ptToIdx(pt, columns);
return getPixel8Bpp(idx);
}
[[nodiscard]]
constexpr auto getPixel(int8_t pBpp, const geo::Point &pt) const noexcept {
const auto idx = ptToIdx(pt, columns);
return getPixel(pBpp, idx);
}
constexpr auto walkPixels(int8_t pBpp, auto callback) const noexcept {
if (pBpp == 4) {
const auto pixelCnt = ox::min<std::size_t>(static_cast<std::size_t>(columns * rows * PixelsPerTile) / 2,
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 = pixels[i] & 0xF;
const auto colorIdx2 = pixels[i] >> 4;
callback(i * 2 + 0, colorIdx1);
callback(i * 2 + 1, colorIdx2);
}
} else {
const auto pixelCnt = ox::min<std::size_t>(static_cast<std::size_t>(columns * rows * PixelsPerTile),
pixels.size());
for (std::size_t i = 0; i < pixelCnt; ++i) {
const auto p = pixels[i];
callback(i, p);
}
}
}
constexpr void setPixel(int8_t pBpp, uint64_t idx, uint8_t palIdx) noexcept {
auto &pixel = this->pixels[idx / 2];
if (pBpp == 4) {
if (idx & 1) {
pixel = (pixel & 0b0000'1111) | (palIdx << 4);
} else {
pixel = (pixel & 0b1111'0000) | (palIdx);
}
} else {
pixel = palIdx;
}
}
constexpr void setPixel(int8_t pBpp, const geo::Point &pt, uint8_t palIdx) noexcept {
const auto idx = ptToIdx(pt, columns);
setPixel(pBpp, idx, palIdx);
}
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");
}
}
/**
* 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]]
constexpr unsigned pixelCnt(int8_t pBpp) const noexcept {
return pBpp == 4 ? pixels.size() * 2 : pixels.size();
}
/**
* Gets the offset in tiles of the desired subsheet.
*/
[[nodiscard]]
constexpr ox::Result<unsigned> getTileOffset(
const auto &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");
}
[[nodiscard]]
constexpr ox::Result<SubSheetId> 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");
}
[[nodiscard]]
constexpr ox::Result<ox::StringView> 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");
}
};
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.TileSheet";
static constexpr auto TypeVersion = 3;
int8_t bpp = 4;
SubSheetId idIt = 0;
ox::FileAddress defaultPalette;
SubSheet subsheet{0, "Root", 1, 1, bpp};
constexpr TileSheet() noexcept = default;
TileSheet(const TileSheet &other) noexcept = default;
inline TileSheet(TileSheet &&other) noexcept:
bpp(other.bpp),
idIt(other.idIt),
defaultPalette(std::move(other.defaultPalette)),
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;
}
[[nodiscard]]
constexpr auto 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.size()) {
out.back().value = pSubsheet->subsheets.size() - 1;
} else {
out.pop_back();
}
return out;
}
return validateSubSheetIdx(pIdx, pIdxIt + 1, &pSubsheet->subsheets[pIdx[pIdxIt]]);
}
/**
* validateSubSheetIdx takes a SubSheetIdx and moves the index to the
* preceding or parent sheet if the current corresponding sheet does
* not exist.
* @param idx SubSheetIdx to validate and correct
* @return a valid version of idx
*/
[[nodiscard]]
constexpr auto validateSubSheetIdx(const SubSheetIdx &idx) noexcept {
return validateSubSheetIdx(idx, 0, &subsheet);
}
[[nodiscard]]
constexpr 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]);
}
[[nodiscard]]
constexpr 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]]);
}
[[nodiscard]]
constexpr const SubSheet &getSubSheet(const SubSheetIdx &idx) const noexcept {
return getSubSheet(idx, 0, &subsheet);
}
[[nodiscard]]
constexpr SubSheet &getSubSheet(const SubSheetIdx &idx) noexcept {
return getSubSheet(idx, 0, &subsheet);
}
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);
}
[[nodiscard]]
constexpr static auto 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]]);
}
[[nodiscard]]
constexpr auto rmSubSheet(const SubSheetIdx &idx) noexcept {
return rmSubSheet(idx, 0, &subsheet);
}
[[nodiscard]]
constexpr auto getPixel4Bpp(
const geo::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);
}
[[nodiscard]]
constexpr auto getPixel8Bpp(
const geo::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);
}
[[nodiscard]]
constexpr auto getIdFor(ox::CRStringView path) const noexcept {
return subsheet.getIdFor(ox::split<8>(path, '.'));
}
constexpr ox::Result<unsigned> getTileOffset(const auto &pNamePath) const noexcept {
return subsheet.getTileOffset(ox::split<8>(pNamePath, '.'), bpp);
}
constexpr ox::Result<ox::StringView> getNameFor(SubSheetId pId) const noexcept {
return subsheet.getNameFor(pId);
}
[[nodiscard]]
auto pixels() const noexcept {
ox::Vector<uint8_t> out;
subsheet.readPixelsTo(&out);
return out;
}
};
struct CompactTileSheet {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.CompactTileSheet";
static constexpr auto TypeVersion = 1;
int8_t bpp = 0;
ox::FileAddress defaultPalette;
ox::Vector<uint8_t> pixels = {};
};
oxModelBegin(TileSheetV1)
oxModelField(bpp)
oxModelField(rows)
oxModelField(columns)
oxModelField(defaultPalette)
oxModelField(pal)
oxModelField(pixels)
oxModelEnd()
oxModelBegin(TileSheetV2::SubSheet)
oxModelField(name);
oxModelField(rows);
oxModelField(columns);
oxModelField(subsheets)
oxModelField(pixels)
oxModelEnd()
oxModelBegin(TileSheetV2)
oxModelField(bpp)
oxModelField(defaultPalette)
oxModelField(subsheet)
oxModelEnd()
oxModelBegin(TileSheet::SubSheet)
oxModelField(name);
oxModelField(rows);
oxModelField(columns);
oxModelField(subsheets)
oxModelField(pixels)
oxModelEnd()
oxModelBegin(TileSheet)
oxModelField(bpp)
oxModelField(idIt)
oxModelField(defaultPalette)
oxModelField(subsheet)
oxModelEnd()
oxModelBegin(CompactTileSheet)
oxModelField(bpp)
oxModelField(defaultPalette)
oxModelField(pixels)
oxModelEnd()
}

View File

@ -0,0 +1,67 @@
/*
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/
#include "typeconv.hpp"
namespace nostalgia::core {
ox::Error NostalgiaPaletteToPaletteConverter::convert(
foundation::Context*,
NostalgiaPalette *src,
Palette *dst) const noexcept {
dst->colors = std::move(src->colors);
return {};
}
ox::Error TileSheetV1ToTileSheetConverter::convert(
foundation::Context*,
TileSheetV1 *src,
TileSheet *dst) const noexcept {
dst->bpp = src->bpp;
dst->defaultPalette = std::move(src->defaultPalette);
dst->subsheet.name = "Root";
dst->subsheet.rows = src->rows;
dst->subsheet.columns = src->columns;
dst->subsheet.pixels = std::move(src->pixels);
return {};
}
ox::Error TileSheetToCompactTileSheetConverter::convert(
foundation::Context*,
TileSheet *src,
CompactTileSheet *dst) const noexcept {
dst->bpp = src->bpp;
dst->defaultPalette = std::move(src->defaultPalette);
dst->pixels = src->pixels();
return {};
}
void TileSheetV2ToTileSheetConverter::convertSubsheet(
TileSheetV2::SubSheet *src,
TileSheet::SubSheet *dst,
SubSheetId *idIt) noexcept {
dst->id = *idIt;
dst->name = std::move(src->name);
dst->columns = src->columns;
dst->rows = src->rows;
dst->pixels = std::move(src->pixels);
++*idIt;
dst->subsheets.resize(src->subsheets.size());
for (auto i = 0u; i < src->subsheets.size(); ++i) {
convertSubsheet(&src->subsheets[i], &dst->subsheets[i], idIt);
}
}
ox::Error TileSheetV2ToTileSheetConverter::convert(
foundation::Context*,
TileSheetV2 *src,
TileSheet *dst) const noexcept {
dst->bpp = src->bpp;
dst->defaultPalette = std::move(src->defaultPalette);
convertSubsheet(&src->subsheet, &dst->subsheet, &dst->idIt);
return {};
}
}

View File

@ -15,32 +15,26 @@ namespace nostalgia::core {
// Type converters // Type converters
struct NostalgiaPaletteToPaletteConverter: public foundation::Converter<NostalgiaPalette, Palette> { class NostalgiaPaletteToPaletteConverter: public foundation::Converter<NostalgiaPalette, Palette> {
ox::Error convert(foundation::Context*, NostalgiaPalette *src, Palette *dst) noexcept final { ox::Error convert(foundation::Context*, NostalgiaPalette *src, Palette *dst) const noexcept final;
dst->colors = std::move(src->colors);
return {};
}
}; };
struct NostalgiaGraphicToTileSheetConverter: public foundation::Converter<NostalgiaGraphic, TileSheet> { class TileSheetV1ToTileSheetConverter: public foundation::Converter<TileSheetV1, TileSheet> {
ox::Error convert(foundation::Context*, NostalgiaGraphic *src, TileSheet *dst) noexcept final { ox::Error convert(foundation::Context*, TileSheetV1 *src, TileSheet *dst) const noexcept final;
dst->bpp = src->bpp;
dst->subsheet.name = "Root";
dst->subsheet.rows = src->rows;
dst->subsheet.columns = src->columns;
dst->defaultPalette = std::move(src->defaultPalette);
dst->subsheet.pixels = std::move(src->pixels);
return {};
}
}; };
struct TileSheetToCompactTileSheetConverter: public foundation::Converter<TileSheet, CompactTileSheet> { class TileSheetToCompactTileSheetConverter: public foundation::Converter<TileSheet, CompactTileSheet> {
ox::Error convert(foundation::Context*, TileSheet *src, CompactTileSheet *dst) noexcept final { ox::Error convert(foundation::Context*, TileSheet *src, CompactTileSheet *dst) const noexcept final;
dst->bpp = src->bpp; };
dst->defaultPalette = std::move(src->defaultPalette);
dst->pixels = src->pixels(); class TileSheetV2ToTileSheetConverter: public foundation::Converter<TileSheetV2, TileSheet> {
return {}; static void convertSubsheet(
} TileSheetV2::SubSheet *src,
TileSheet::SubSheet *dst,
SubSheetId *idIt) noexcept;
ox::Error convert(foundation::Context*, TileSheetV2 *src, TileSheet *dst) const noexcept final;
}; };
} }

View File

@ -511,7 +511,10 @@ void setSprite(Context *ctx,
} }
void setTile(Context *ctx, unsigned bgIdx, int column, int row, uint8_t tile) noexcept { void setTile(Context *ctx, unsigned bgIdx, int column, int row, uint8_t tile) noexcept {
//oxTracef("nostalgia::core::gfx::gl", "setTile(ctx, {}, {}, {}, {})", bgIdx, column, row, tile); oxTracef(
"nostalgia::core::gfx::setTile",
"bgIdx: {}, column: {}, row: {}, tile: {}",
bgIdx, column, row, tile);
const auto id = ctx->rendererData<renderer::GlImplData>(); const auto id = ctx->rendererData<renderer::GlImplData>();
const auto z = static_cast<unsigned>(bgIdx); const auto z = static_cast<unsigned>(bgIdx);
const auto y = static_cast<unsigned>(row); const auto y = static_cast<unsigned>(row);
@ -520,8 +523,10 @@ void setTile(Context *ctx, unsigned bgIdx, int column, int row, uint8_t tile) no
auto &bg = id->cbbs[z]; auto &bg = id->cbbs[z];
auto vbo = &bg.vertices[i * renderer::BgVertexVboLength]; auto vbo = &bg.vertices[i * renderer::BgVertexVboLength];
auto ebo = &bg.elements[i * renderer::BgVertexEboLength]; auto ebo = &bg.elements[i * renderer::BgVertexEboLength];
renderer::setTileBufferObject(ctx, i * renderer::BgVertexVboRows, renderer::setTileBufferObject(
static_cast<float>(x), static_cast<float>(y), tile, vbo, ebo); ctx, i * renderer::BgVertexVboRows,
static_cast<float>(x), static_cast<float>(y),
tile, vbo, ebo);
bg.updated = true; bg.updated = true;
} }

View File

@ -21,7 +21,7 @@ class Context {
ox::StringView appName = "Nostalgia Foundation App"; ox::StringView appName = "Nostalgia Foundation App";
#ifndef OX_BARE_METAL #ifndef OX_BARE_METAL
AssetManager assetManager; AssetManager assetManager;
ox::Vector<class BaseConverter*> converters; ox::Vector<const class BaseConverter*> converters;
ox::Vector<PackTransform> packTransforms; ox::Vector<PackTransform> packTransforms;
#else #else
std::size_t preloadSectionOffset = 0; std::size_t preloadSectionOffset = 0;

View File

@ -18,7 +18,7 @@ const ox::Vector<const Module*> *modules() noexcept {
} }
ox::Vector<foundation::BaseConverter*> Module::converters() const noexcept { ox::Vector<const foundation::BaseConverter*> Module::converters() const noexcept {
return {}; return {};
} }

View File

@ -19,7 +19,7 @@ class Module {
Module &operator=(Module&&) noexcept = delete; Module &operator=(Module&&) noexcept = delete;
constexpr virtual ~Module() noexcept = default; constexpr virtual ~Module() noexcept = default;
[[nodiscard]] [[nodiscard]]
virtual ox::Vector<foundation::BaseConverter*> converters() const noexcept; virtual ox::Vector<const foundation::BaseConverter*> converters() const noexcept;
[[nodiscard]] [[nodiscard]]
virtual ox::Vector<PackTransform> packTransforms() const noexcept; virtual ox::Vector<PackTransform> packTransforms() const noexcept;
}; };

View File

@ -11,9 +11,10 @@ namespace nostalgia::foundation {
#ifndef OX_BARE_METAL #ifndef OX_BARE_METAL
[[nodiscard]] [[nodiscard]]
static auto findConverter(foundation::Context *ctx, static ox::Result<const BaseConverter*> findConverter(
foundation::Context *ctx,
ox::CRStringView srcTypeName, int srcTypeVersion, ox::CRStringView srcTypeName, int srcTypeVersion,
ox::CRStringView dstTypeName, int dstTypeVersion) noexcept -> ox::Result<BaseConverter*> { ox::CRStringView dstTypeName, int dstTypeVersion) noexcept {
for (auto &c : ctx->converters) { for (auto &c : ctx->converters) {
if (c->matches(srcTypeName, srcTypeVersion, dstTypeName, dstTypeVersion)) { if (c->matches(srcTypeName, srcTypeVersion, dstTypeName, dstTypeVersion)) {
return c; return c;
@ -22,13 +23,14 @@ static auto findConverter(foundation::Context *ctx,
return OxError(1, "Could not find converter"); return OxError(1, "Could not find converter");
}; };
static ox::Result<ox::UniquePtr<Wrap>> convert(foundation::Context *ctx, const ox::Buffer &srcBuffer, static ox::Result<ox::UniquePtr<Wrap>> convert(
foundation::Context *ctx, const ox::Buffer &srcBuffer,
ox::CRStringView srcTypeName, int srcTypeVersion, ox::CRStringView srcTypeName, int srcTypeVersion,
ox::CRStringView dstTypeName, int dstTypeVersion) noexcept { ox::CRStringView dstTypeName, int dstTypeVersion) noexcept {
// look for direct converter // look for direct converter
auto [c, err] = findConverter(ctx, srcTypeName, srcTypeVersion, dstTypeName, dstTypeVersion); auto [c, err] = findConverter(ctx, srcTypeName, srcTypeVersion, dstTypeName, dstTypeVersion);
if (!err) { if (!err) {
return c->convertBuffToPtr(nullptr, srcBuffer); return c->convertBuffToPtr(ctx, srcBuffer);
} }
// try to chain multiple converters // try to chain multiple converters
for (const auto &subConverter : ctx->converters) { for (const auto &subConverter : ctx->converters) {
@ -45,7 +47,11 @@ static ox::Result<ox::UniquePtr<Wrap>> convert(foundation::Context *ctx, const o
return OxError(1, "Could not convert between types"); return OxError(1, "Could not convert between types");
} }
ox::Result<ox::UniquePtr<Wrap>> convert(foundation::Context *ctx, const ox::Buffer &srcBuffer, ox::CRStringView dstTypeName, int dstTypeVersion) noexcept { ox::Result<ox::UniquePtr<Wrap>> convert(
foundation::Context *ctx,
const ox::Buffer &srcBuffer,
ox::CRStringView dstTypeName,
int dstTypeVersion) noexcept {
oxRequire(hdr, ox::readClawHeader(srcBuffer)); oxRequire(hdr, ox::readClawHeader(srcBuffer));
return convert(ctx, srcBuffer, hdr.typeName, hdr.typeVersion, dstTypeName, dstTypeVersion); return convert(ctx, srcBuffer, hdr.typeName, hdr.typeVersion, dstTypeName, dstTypeVersion);
} }

View File

@ -53,20 +53,20 @@ class BaseConverter {
virtual ~BaseConverter() noexcept = default; virtual ~BaseConverter() noexcept = default;
[[nodiscard]] [[nodiscard]]
virtual ox::StringView srcTypeName() noexcept = 0; virtual ox::StringView srcTypeName() const noexcept = 0;
[[nodiscard]] [[nodiscard]]
virtual int srcTypeVersion() noexcept = 0; virtual int srcTypeVersion() const noexcept = 0;
[[nodiscard]] [[nodiscard]]
virtual bool srcMatches(ox::CRStringView srcTypeName, int srcTypeVersion) const noexcept = 0; virtual bool srcMatches(ox::CRStringView pSrcTypeName, int pSrcTypeVersion) const noexcept = 0;
[[nodiscard]] [[nodiscard]]
virtual bool dstMatches(ox::CRStringView dstTypeName, int dstTypeVersion) const noexcept = 0; virtual bool dstMatches(ox::CRStringView dstTypeName, int dstTypeVersion) const noexcept = 0;
virtual ox::Result<ox::UniquePtr<Wrap>> convertPtrToPtr(foundation::Context *ctx, Wrap *src) noexcept = 0; virtual ox::Result<ox::UniquePtr<Wrap>> convertPtrToPtr(foundation::Context *ctx, Wrap *src) const noexcept = 0;
virtual ox::Result<ox::UniquePtr<Wrap>> convertBuffToPtr(foundation::Context *ctx, const ox::Buffer &srcBuff) noexcept = 0; virtual ox::Result<ox::UniquePtr<Wrap>> convertBuffToPtr(foundation::Context *ctx, const ox::Buffer &srcBuff) const noexcept = 0;
[[nodiscard]] [[nodiscard]]
inline bool matches(ox::CRStringView srcTypeName, int srcTypeVersion, inline bool matches(ox::CRStringView srcTypeName, int srcTypeVersion,
@ -80,47 +80,48 @@ class BaseConverter {
template<typename SrcType, typename DstType> template<typename SrcType, typename DstType>
class Converter: public BaseConverter { class Converter: public BaseConverter {
public: public:
virtual ox::Error convert(foundation::Context *ctx, SrcType*, DstType*) noexcept = 0;
[[nodiscard]] [[nodiscard]]
ox::StringView srcTypeName() noexcept final { ox::StringView srcTypeName() const noexcept final {
return ox::requireModelTypeName<SrcType>(); return ox::requireModelTypeName<SrcType>();
} }
[[nodiscard]] [[nodiscard]]
int srcTypeVersion() noexcept final { int srcTypeVersion() const noexcept final {
return ox::requireModelTypeVersion<SrcType>(); return ox::requireModelTypeVersion<SrcType>();
} }
[[nodiscard]] [[nodiscard]]
bool srcMatches(ox::CRStringView srcTypeName, int srcTypeVersion) const noexcept final { bool srcMatches(ox::CRStringView pSrcTypeName, int pSrcTypeVersion) const noexcept final {
static constexpr auto SrcTypeName = ox::requireModelTypeName<SrcType>(); static const auto SrcTypeName = ox::requireModelTypeName<SrcType>();
static constexpr auto SrcTypeVersion = ox::requireModelTypeVersion<SrcType>(); static const auto SrcTypeVersion = ox::requireModelTypeVersion<SrcType>();
return ox_strcmp(srcTypeName, SrcTypeName) == 0 return pSrcTypeName == SrcTypeName
&& srcTypeVersion == SrcTypeVersion; && pSrcTypeVersion == SrcTypeVersion;
} }
[[nodiscard]] [[nodiscard]]
bool dstMatches(ox::CRStringView dstTypeName, int dstTypeVersion) const noexcept final { bool dstMatches(ox::CRStringView dstTypeName, int dstTypeVersion) const noexcept final {
static constexpr auto DstTypeName = ox::requireModelTypeName<DstType>(); static const auto DstTypeName = ox::StringView(ox::requireModelTypeName<DstType>());
static constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>(); static const auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
return ox_strcmp(dstTypeName, DstTypeName) == 0 return dstTypeName == DstTypeName
&& dstTypeVersion == DstTypeVersion; && dstTypeVersion == DstTypeVersion;
} }
ox::Result<ox::UniquePtr<Wrap>> convertPtrToPtr(foundation::Context *ctx, Wrap *src) noexcept final { ox::Result<ox::UniquePtr<Wrap>> convertPtrToPtr(foundation::Context *ctx, Wrap *src) const noexcept final {
auto dst = makeWrap<DstType>(); auto dst = makeWrap<DstType>();
oxReturnError(convert(ctx, wrapCast<SrcType>(src), wrapCast<DstType>(dst.get()))); oxReturnError(convert(ctx, wrapCast<SrcType>(src), wrapCast<DstType>(dst.get())));
return ox::Result<ox::UniquePtr<Wrap>>(std::move(dst)); return ox::Result<ox::UniquePtr<Wrap>>(std::move(dst));
} }
ox::Result<ox::UniquePtr<Wrap>> convertBuffToPtr(foundation::Context *ctx, const ox::Buffer &srcBuff) noexcept final { ox::Result<ox::UniquePtr<Wrap>> convertBuffToPtr(foundation::Context *ctx, const ox::Buffer &srcBuff) const noexcept final {
oxRequireM(src, ox::readClaw<SrcType>(srcBuff)); oxRequireM(src, ox::readClaw<SrcType>(srcBuff));
auto dst = makeWrap<DstType>(); auto dst = makeWrap<DstType>();
oxReturnError(convert(ctx, &src, wrapCast<DstType>(dst.get()))); oxReturnError(convert(ctx, &src, wrapCast<DstType>(dst.get())));
return ox::Result<ox::UniquePtr<Wrap>>(std::move(dst)); return ox::Result<ox::UniquePtr<Wrap>>(std::move(dst));
} }
protected:
virtual ox::Error convert(foundation::Context *ctx, SrcType*, DstType*) const noexcept = 0;
}; };
ox::Result<ox::UniquePtr<Wrap>> convert(foundation::Context *ctx, const ox::Buffer &srcBuffer, ox::Result<ox::UniquePtr<Wrap>> convert(foundation::Context *ctx, const ox::Buffer &srcBuffer,

View File

@ -4,41 +4,19 @@
#include <nostalgia/core/core.hpp> #include <nostalgia/core/core.hpp>
#include <nostalgia/foundation/media.hpp> #include <nostalgia/foundation/media.hpp>
#include <nostalgia/scene/scene.hpp>
using namespace nostalgia; using namespace nostalgia;
static int spriteX = 72; static bool s_paused = false;
static int spriteY = 64; static ox::Optional<scene::Scene> s_scene;
static ox::StringView sprites = "nostalgia";
static bool paused = false;
static int updateHandler(core::Context *ctx) noexcept { static int updateHandler(core::Context*) noexcept {
constexpr auto sleepTime = 16; constexpr auto sleepTime = 16;
if (paused) { if (s_paused) {
return sleepTime; return sleepTime;
} }
int xmod = 0; // do stuff
int ymod = 0;
if (buttonDown(ctx, core::Alpha_D) || buttonDown(ctx, core::GamePad_Right)) {
xmod = 2;
} else if (buttonDown(ctx, core::Alpha_A) || buttonDown(ctx, core::GamePad_Left)) {
xmod = -2;
}
if (buttonDown(ctx, core::Alpha_S) || buttonDown(ctx, core::GamePad_Down)) {
ymod = 2;
} else if (buttonDown(ctx, core::Alpha_W) || buttonDown(ctx, core::GamePad_Up)) {
ymod = -2;
}
if (!xmod && !ymod) {
spriteX += 1;
}
spriteX += xmod;
spriteY += ymod;
//constexpr ox::StringView sprites = "nostalgia";
for (unsigned i = 0; i < sprites.len(); ++i) {
const auto c = static_cast<unsigned>(sprites[i] - ('a' - 1));
core::setSprite(ctx, i, spriteX + 8 * (static_cast<int>(i) + 1), spriteY, c, 0, 0, 0);
}
return sleepTime; return sleepTime;
} }
@ -47,7 +25,7 @@ static void keyEventHandler(core::Context *ctx, core::Key key, bool down) noexce
if (key == core::Key::Alpha_Q) { if (key == core::Key::Alpha_Q) {
core::shutdown(ctx); core::shutdown(ctx);
} else if (key == core::Key::Alpha_P) { } else if (key == core::Key::Alpha_P) {
paused = !paused; s_paused = !s_paused;
} }
} }
} }
@ -55,13 +33,11 @@ static void keyEventHandler(core::Context *ctx, core::Key key, bool down) noexce
ox::Error run(ox::UniquePtr<ox::FileSystem> fs) noexcept { ox::Error run(ox::UniquePtr<ox::FileSystem> fs) noexcept {
oxTraceInitHook(); oxTraceInitHook();
oxRequireM(ctx, core::init(std::move(fs))); oxRequireM(ctx, core::init(std::move(fs)));
constexpr ox::FileAddress TileSheetAddr("/TileSheets/Charset.ng"); constexpr ox::FileAddress SceneAddr("/Scenes/Chester.nscn");
constexpr ox::FileAddress PaletteAddr("/Palettes/Charset.npal"); oxRequire(scn, foundation::readObj<scene::SceneStatic>(ctx.get(), SceneAddr));
oxRequire(tsStat, ctx->rom->stat(PaletteAddr));
oxReturnError(core::loadSpriteTileSheet(ctx.get(), TileSheetAddr, PaletteAddr));
oxReturnError(core::initConsole(ctx.get()));
core::puts(ctx.get(), 10, 9, "DOPENESS!!!");
core::setUpdateHandler(ctx.get(), updateHandler); core::setUpdateHandler(ctx.get(), updateHandler);
core::setKeyEventHandler(ctx.get(), keyEventHandler); core::setKeyEventHandler(ctx.get(), keyEventHandler);
s_scene.emplace(scn.get());
oxReturnError(s_scene->setupDisplay(ctx.get()));
return core::run(ctx.get()); return core::run(ctx.get());
} }

View File

@ -2,6 +2,7 @@
add_library( add_library(
NostalgiaScene NostalgiaScene
scene.cpp scene.cpp
scenestatic.cpp
scenemodule.cpp scenemodule.cpp
typeconv.cpp typeconv.cpp
) )
@ -9,11 +10,12 @@ add_library(
target_link_libraries( target_link_libraries(
NostalgiaScene PUBLIC NostalgiaScene PUBLIC
NostalgiaCore NostalgiaCore
NostalgiaGeo
) )
install( install(
FILES FILES
scene.hpp scenestatic.hpp
scenemodule.hpp scenemodule.hpp
typeconv.hpp typeconv.hpp
DESTINATION DESTINATION

View File

@ -1,11 +1,46 @@
/* /*
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved. * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/ */
#include <nostalgia/core/gfx.hpp>
#include "scene.hpp" #include "scene.hpp"
namespace nostalgia::scene { namespace nostalgia::scene {
Scene::Scene(const SceneStatic *sceneStatic) noexcept:
m_sceneStatic(sceneStatic) {
}
ox::Error Scene::setupDisplay(core::Context *ctx) noexcept {
if (m_sceneStatic->palettes.empty()) {
return OxError(1, "Scene has no palettes");
}
const auto &palette = m_sceneStatic->palettes[0];
oxReturnError(core::loadBgTileSheet(
ctx, 0, m_sceneStatic->tilesheet, palette));
// disable all backgrounds
core::setBgStatus(ctx, 0);
for (auto layerNo = 0u; const auto &layer : m_sceneStatic->tileMapIdx) {
core::setBgStatus(ctx, layerNo, true);
core::setBgCbb(ctx, layerNo, 0);
auto x = 0;
auto y = 0;
auto width = m_sceneStatic->rows[layerNo];
for (const auto &tile : layer) {
core::setTile(ctx, layerNo, x, y, tile);
core::setTile(ctx, layerNo, x + 1, y, tile + 1);
core::setTile(ctx, layerNo, x, y + 1, tile + 2);
core::setTile(ctx, layerNo, x + 1, y + 1, tile + 3);
x += 2;
if (x >= width * 2) {
x = 0;
y += 2;
}
}
++layerNo;
}
return {};
}
} }

View File

@ -4,104 +4,19 @@
#pragma once #pragma once
#include <ox/fs/fs.hpp> #include "scenestatic.hpp"
#include <ox/std/error.hpp>
#include <ox/std/types.hpp>
#include <ox/std/vector.hpp>
namespace nostalgia::scene { namespace nostalgia::scene {
struct TileDoc { class Scene {
private:
const SceneStatic *m_sceneStatic = nullptr;
constexpr static auto TypeName = "net.drinkingtea.nostalgia.scene.TileDoc"; public:
constexpr static auto TypeVersion = 1; explicit Scene(const SceneStatic *sceneStatic) noexcept;
constexpr static auto Preloadable = true;
ox::String sheetIdx; ox::Error setupDisplay(core::Context *ctx) noexcept;
uint8_t type = 0;
}; };
oxModelBegin(TileDoc)
oxModelFieldRename(sheet_idx, sheetIdx);
oxModelField(type);
oxModelEnd()
struct SceneDoc {
using TileMapRow = ox::Vector<TileDoc>;
using TileMapLayer = ox::Vector<TileMapRow>;
using TileMap = ox::Vector<TileMapLayer>;
constexpr static auto TypeName = "net.drinkingtea.nostalgia.scene.SceneDoc";
constexpr static auto TypeVersion = 1;
constexpr static auto Preloadable = true;
ox::FileAddress tilesheet;
ox::FileAddress palette;
TileMap tiles;
};
oxModelBegin(SceneDoc)
oxModelField(tilesheet)
oxModelField(palette)
oxModelField(tiles)
oxModelEnd()
struct Scene {
constexpr static auto TypeName = "net.drinkingtea.nostalgia.scene.Scene";
constexpr static auto TypeVersion = 1;
constexpr static auto Preloadable = true;
struct Tile {
uint16_t &tileMapIdx;
uint8_t &tileType;
constexpr Tile(uint16_t &pTileMapIdx, uint8_t &pTileType) noexcept:
tileMapIdx(pTileMapIdx),
tileType(pTileType) {
}
};
struct Layer {
uint16_t &columns;
uint16_t &rows;
uint16_t *tileMapIdx = nullptr;
uint8_t *tileType = nullptr;
constexpr Layer(uint16_t &pColumns,
uint16_t &pRows,
uint16_t *pTileMapIdx,
uint8_t *pTileType) noexcept:
columns(pColumns),
rows(pRows),
tileMapIdx(pTileMapIdx),
tileType(pTileType) {
}
[[nodiscard]]
constexpr Tile tile(std::size_t i) const noexcept {
return {tileMapIdx[i], tileType[i]};
}
};
uint16_t layers = 0;
ox::Vector<uint16_t> columns;
ox::Vector<uint16_t> rows;
ox::Vector<ox::Vector<uint16_t>> tileMapIdx;
ox::Vector<ox::Vector<uint8_t>> tileType;
[[nodiscard]]
constexpr Layer layer(std::size_t i) noexcept {
return {columns[i], rows[i], tileMapIdx[i].data(), tileType[i].data()};
}
};
oxModelBegin(Scene)
oxModelField(layers)
oxModelField(columns)
oxModelField(rows)
oxModelFieldRename(tile_map_idx, tileMapIdx)
oxModelFieldRename(tile_type, tileType)
oxModelEnd()
} }

View File

@ -10,15 +10,15 @@ namespace nostalgia::scene {
SceneModule SceneModule::mod; SceneModule SceneModule::mod;
ox::Vector<foundation::BaseConverter*> SceneModule::converters() const noexcept { ox::Vector<const foundation::BaseConverter*> SceneModule::converters() const noexcept {
return { return {
&sceneToSceneInstaceConverter, &sceneDocToSceneStaticConverter,
}; };
} }
ox::Vector<foundation::PackTransform> SceneModule::packTransforms() const noexcept { ox::Vector<foundation::PackTransform> SceneModule::packTransforms() const noexcept {
return { return {
foundation::transformRule<SceneDoc, Scene>, foundation::transformRule<SceneDoc, SceneStatic>,
}; };
} }

View File

@ -12,12 +12,12 @@ namespace nostalgia::scene {
class SceneModule: public foundation::Module { class SceneModule: public foundation::Module {
private: private:
mutable SceneDocToSceneConverter sceneToSceneInstaceConverter; SceneDocToSceneStaticConverter sceneDocToSceneStaticConverter;
public: public:
static SceneModule mod; static SceneModule mod;
[[nodiscard]] [[nodiscard]]
ox::Vector<foundation::BaseConverter*> converters() const noexcept override; ox::Vector<const foundation::BaseConverter*> converters() const noexcept override;
[[nodiscard]] [[nodiscard]]
ox::Vector<foundation::PackTransform> packTransforms() const noexcept override; ox::Vector<foundation::PackTransform> packTransforms() const noexcept override;
}; };

View File

@ -0,0 +1,11 @@
/*
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/
#include "scenestatic.hpp"
namespace nostalgia::scene {
}

View File

@ -0,0 +1,164 @@
/*
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/
#pragma once
#include <ox/fs/fs.hpp>
#include <ox/std/error.hpp>
#include <ox/std/types.hpp>
#include <ox/std/vector.hpp>
#include <nostalgia/core/tilesheet.hpp>
#include <nostalgia/geo/size.hpp>
namespace nostalgia::scene {
struct TileDoc {
constexpr static auto TypeName = "net.drinkingtea.nostalgia.scene.TileDoc";
constexpr static auto TypeVersion = 1;
constexpr static auto Preloadable = true;
core::SubSheetId subsheetId = -1;
ox::String subsheetPath;
uint8_t type = 0;
[[nodiscard]]
constexpr ox::Result<core::SubSheetId> getSubsheetId(const core::TileSheet &ts) const noexcept {
// prefer the already present ID
if (subsheetId > -1) {
return subsheetId;
}
return ts.getIdFor(subsheetPath);
}
[[nodiscard]]
constexpr ox::Result<ox::StringView> getSubsheetPath(
const core::TileSheet &ts) const noexcept {
// prefer the already present path
if (!subsheetPath.len()) {
return ts.getNameFor(subsheetId);
}
return ox::StringView(subsheetPath);
}
};
oxModelBegin(TileDoc)
oxModelFieldRename(subsheet_id, subsheetId);
oxModelFieldRename(subsheet_path, subsheetPath);
oxModelField(type);
oxModelEnd()
struct SceneDoc {
using TileMapRow = ox::Vector<TileDoc>;
using TileMapLayer = ox::Vector<TileMapRow>;
using TileMap = ox::Vector<TileMapLayer>;
constexpr static auto TypeName = "net.drinkingtea.nostalgia.scene.SceneDoc";
constexpr static auto TypeVersion = 1;
constexpr static auto Preloadable = true;
ox::String tilesheet; // path
ox::Vector<ox::String> palettes; // paths
TileMap tiles;
[[nodiscard]]
constexpr geo::Size size(std::size_t layerIdx) const noexcept {
const auto &layer = this->tiles[layerIdx];
const auto rowCnt = static_cast<int>(layer.size());
if (!rowCnt) {
return {};
}
auto colCnt = layer[0].size();
// find shortest row (they should all be the same, but you know this data
// could come from a file)
for (const auto &row : layer) {
colCnt = ox::min(colCnt, row.size());
}
return {static_cast<int>(colCnt), rowCnt};
}
};
oxModelBegin(SceneDoc)
oxModelField(tilesheet)
oxModelField(palettes)
oxModelField(tiles)
oxModelEnd()
struct SceneStatic {
constexpr static auto TypeName = "net.drinkingtea.nostalgia.scene.SceneStatic";
constexpr static auto TypeVersion = 1;
constexpr static auto Preloadable = true;
struct Tile {
uint16_t &tileMapIdx;
uint8_t &tileType;
constexpr Tile(uint16_t *pTileMapIdx, uint8_t *pTileType) noexcept:
tileMapIdx(*pTileMapIdx),
tileType(*pTileType) {
}
};
struct Layer {
uint16_t &columns;
uint16_t &rows;
ox::Vector<uint16_t> &tileMapIdx;
ox::Vector<uint8_t> &tileType;
constexpr Layer(
uint16_t *pColumns,
uint16_t *pRows,
ox::Vector<uint16_t> *pTileMapIdx,
ox::Vector<uint8_t> *pTileType) noexcept:
columns(*pColumns),
rows(*pRows),
tileMapIdx(*pTileMapIdx),
tileType(*pTileType) {
}
[[nodiscard]]
constexpr Tile tile(std::size_t i) noexcept {
return {&tileMapIdx[i], &tileType[i]};
}
constexpr auto setDimensions(geo::Size dim) noexcept {
columns = dim.width;
rows = dim.height;
const auto tileCnt = static_cast<unsigned>(columns * rows);
tileMapIdx.resize(tileCnt);
tileType.resize(tileCnt);
}
};
ox::FileAddress tilesheet;
ox::Vector<ox::FileAddress> palettes;
// tile layer data
ox::Vector<uint16_t> columns;
ox::Vector<uint16_t> rows;
ox::Vector<ox::Vector<uint16_t>> tileMapIdx;
ox::Vector<ox::Vector<uint8_t>> tileType;
[[nodiscard]]
constexpr Layer layer(std::size_t i) noexcept {
return {&columns[i], &rows[i], &tileMapIdx[i], &tileType[i]};
}
constexpr auto setLayerCnt(std::size_t layerCnt) noexcept {
this->columns.resize(layerCnt);
this->rows.resize(layerCnt);
this->tileMapIdx.resize(layerCnt);
this->tileType.resize(layerCnt);
}
};
oxModelBegin(SceneStatic)
oxModelField(tilesheet)
oxModelField(palettes)
oxModelField(columns)
oxModelField(rows)
oxModelFieldRename(tile_map_idx, tileMapIdx)
oxModelFieldRename(tile_type, tileType)
oxModelEnd()
}

View File

@ -2,13 +2,41 @@
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved. * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/ */
#include <nostalgia/core/gfx.hpp>
#include <nostalgia/foundation/media.hpp>
#include "typeconv.hpp" #include "typeconv.hpp"
namespace nostalgia::scene { namespace nostalgia::scene {
// Type converters ox::Error SceneDocToSceneStaticConverter::convert(
foundation::Context *ctx,
ox::Error SceneDocToSceneConverter::convert(foundation::Context*, SceneDoc *, Scene *) noexcept { SceneDoc *src,
SceneStatic *dst) const noexcept {
oxRequire(ts, foundation::readObj<core::TileSheet>(ctx, src->tilesheet));
const auto layerCnt = src->tiles.size();
dst->setLayerCnt(layerCnt);
dst->tilesheet = ox::FileAddress(src->tilesheet);
dst->palettes.reserve(src->palettes.size());
for (const auto &pal : src->palettes) {
dst->palettes.emplace_back(pal);
}
for (auto layerIdx = 0u; const auto &layer : src->tiles) {
const auto layerDim = src->size(layerIdx);
auto dstLayer = dst->layer(layerIdx);
dstLayer.setDimensions(layerDim);
for (auto tileIdx = 0u; const auto &row : layer) {
for (const auto &srcTile : row) {
auto dstTile = dstLayer.tile(tileIdx);
dstTile.tileType = srcTile.type;
oxRequire(path, srcTile.getSubsheetPath(*ts));
oxRequire(mapIdx, ts->getTileOffset(path));
dstTile.tileMapIdx = static_cast<uint16_t>(mapIdx);
++tileIdx;
}
}
++layerIdx;
}
return {}; return {};
} }

View File

@ -6,12 +6,12 @@
#include <nostalgia/foundation/typeconv.hpp> #include <nostalgia/foundation/typeconv.hpp>
#include "scene.hpp" #include "scenestatic.hpp"
namespace nostalgia::scene { namespace nostalgia::scene {
struct SceneDocToSceneConverter: public foundation::Converter<SceneDoc, Scene> { class SceneDocToSceneStaticConverter: public foundation::Converter<SceneDoc, SceneStatic> {
ox::Error convert(foundation::Context*, SceneDoc *src, Scene *dst) noexcept final; ox::Error convert(foundation::Context*, SceneDoc *src, SceneStatic *dst) const noexcept final;
}; };
} }