nostalgia/src/nostalgia/scene/scenestatic.hpp

165 lines
4.0 KiB
C++

/*
* 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()
}