[nostalgia] Fill out basic Scene system functionality
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
add_library(
|
||||
NostalgiaScene
|
||||
scene.cpp
|
||||
scenestatic.cpp
|
||||
scenemodule.cpp
|
||||
typeconv.cpp
|
||||
)
|
||||
@@ -9,11 +10,12 @@ add_library(
|
||||
target_link_libraries(
|
||||
NostalgiaScene PUBLIC
|
||||
NostalgiaCore
|
||||
NostalgiaGeo
|
||||
)
|
||||
|
||||
install(
|
||||
FILES
|
||||
scene.hpp
|
||||
scenestatic.hpp
|
||||
scenemodule.hpp
|
||||
typeconv.hpp
|
||||
DESTINATION
|
||||
|
||||
@@ -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"
|
||||
|
||||
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 {};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,104 +4,19 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ox/fs/fs.hpp>
|
||||
#include <ox/std/error.hpp>
|
||||
#include <ox/std/types.hpp>
|
||||
#include <ox/std/vector.hpp>
|
||||
#include "scenestatic.hpp"
|
||||
|
||||
namespace nostalgia::scene {
|
||||
|
||||
struct TileDoc {
|
||||
class Scene {
|
||||
private:
|
||||
const SceneStatic *m_sceneStatic = nullptr;
|
||||
|
||||
constexpr static auto TypeName = "net.drinkingtea.nostalgia.scene.TileDoc";
|
||||
constexpr static auto TypeVersion = 1;
|
||||
constexpr static auto Preloadable = true;
|
||||
public:
|
||||
explicit Scene(const SceneStatic *sceneStatic) noexcept;
|
||||
|
||||
ox::String sheetIdx;
|
||||
uint8_t type = 0;
|
||||
ox::Error setupDisplay(core::Context *ctx) noexcept;
|
||||
|
||||
};
|
||||
|
||||
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()
|
||||
|
||||
}
|
||||
|
||||
@@ -10,15 +10,15 @@ namespace nostalgia::scene {
|
||||
|
||||
SceneModule SceneModule::mod;
|
||||
|
||||
ox::Vector<foundation::BaseConverter*> SceneModule::converters() const noexcept {
|
||||
ox::Vector<const foundation::BaseConverter*> SceneModule::converters() const noexcept {
|
||||
return {
|
||||
&sceneToSceneInstaceConverter,
|
||||
&sceneDocToSceneStaticConverter,
|
||||
};
|
||||
}
|
||||
|
||||
ox::Vector<foundation::PackTransform> SceneModule::packTransforms() const noexcept {
|
||||
return {
|
||||
foundation::transformRule<SceneDoc, Scene>,
|
||||
foundation::transformRule<SceneDoc, SceneStatic>,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -12,12 +12,12 @@ namespace nostalgia::scene {
|
||||
|
||||
class SceneModule: public foundation::Module {
|
||||
private:
|
||||
mutable SceneDocToSceneConverter sceneToSceneInstaceConverter;
|
||||
SceneDocToSceneStaticConverter sceneDocToSceneStaticConverter;
|
||||
|
||||
public:
|
||||
static SceneModule mod;
|
||||
[[nodiscard]]
|
||||
ox::Vector<foundation::BaseConverter*> converters() const noexcept override;
|
||||
ox::Vector<const foundation::BaseConverter*> converters() const noexcept override;
|
||||
[[nodiscard]]
|
||||
ox::Vector<foundation::PackTransform> packTransforms() const noexcept override;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include "scenestatic.hpp"
|
||||
|
||||
namespace nostalgia::scene {
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
}
|
||||
@@ -2,13 +2,41 @@
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include <nostalgia/core/gfx.hpp>
|
||||
#include <nostalgia/foundation/media.hpp>
|
||||
|
||||
#include "typeconv.hpp"
|
||||
|
||||
namespace nostalgia::scene {
|
||||
|
||||
// Type converters
|
||||
|
||||
ox::Error SceneDocToSceneConverter::convert(foundation::Context*, SceneDoc *, Scene *) noexcept {
|
||||
ox::Error SceneDocToSceneStaticConverter::convert(
|
||||
foundation::Context *ctx,
|
||||
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 {};
|
||||
}
|
||||
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
|
||||
#include <nostalgia/foundation/typeconv.hpp>
|
||||
|
||||
#include "scene.hpp"
|
||||
#include "scenestatic.hpp"
|
||||
|
||||
namespace nostalgia::scene {
|
||||
|
||||
struct SceneDocToSceneConverter: public foundation::Converter<SceneDoc, Scene> {
|
||||
ox::Error convert(foundation::Context*, SceneDoc *src, Scene *dst) noexcept final;
|
||||
class SceneDocToSceneStaticConverter: public foundation::Converter<SceneDoc, SceneStatic> {
|
||||
ox::Error convert(foundation::Context*, SceneDoc *src, SceneStatic *dst) const noexcept final;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user