[nostalgia] Add start for Scene editor in Studio
This commit is contained in:
parent
19d5641c6e
commit
ae9272841f
@ -2,8 +2,6 @@
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include <ox/std/array.hpp>
|
||||
|
||||
#include <nostalgia/foundation/module.hpp>
|
||||
|
||||
#include <nostalgia/core/module.hpp>
|
||||
@ -16,8 +14,8 @@ void loadModules() noexcept {
|
||||
if (modulesLoaded) {
|
||||
return;
|
||||
}
|
||||
foundation::registerModule(&core::CoreModule::mod);
|
||||
foundation::registerModule(&scene::SceneModule::mod);
|
||||
foundation::registerModule(core::module());
|
||||
foundation::registerModule(scene::module());
|
||||
modulesLoaded = true;
|
||||
}
|
||||
|
||||
|
@ -7,12 +7,6 @@ add_library(
|
||||
typestore.cpp
|
||||
)
|
||||
|
||||
add_library(
|
||||
NostalgiaCore-Headless
|
||||
headless/core.cpp
|
||||
headless/gfx.cpp
|
||||
)
|
||||
|
||||
add_library(NostalgiaCore)
|
||||
|
||||
if(NOT NOSTALGIA_BUILD_TYPE STREQUAL "GBA")
|
||||
@ -65,11 +59,6 @@ target_link_libraries(
|
||||
NostalgiaCore-Common
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
NostalgiaCore-Headless PUBLIC
|
||||
NostalgiaCore-Common
|
||||
)
|
||||
|
||||
if(NOSTALGIA_BUILD_STUDIO)
|
||||
add_subdirectory(studio)
|
||||
endif()
|
||||
@ -84,7 +73,9 @@ install(
|
||||
core.hpp
|
||||
event.hpp
|
||||
gfx.hpp
|
||||
ptidxconv.hpp
|
||||
input.hpp
|
||||
tilesheet.hpp
|
||||
typeconv.hpp
|
||||
typestore.hpp
|
||||
DESTINATION
|
||||
@ -94,7 +85,6 @@ install(
|
||||
install(
|
||||
TARGETS
|
||||
NostalgiaCore
|
||||
NostalgiaCore-Headless
|
||||
DESTINATION
|
||||
LIBRARY DESTINATION lib/nostalgia
|
||||
ARCHIVE DESTINATION lib/nostalgia
|
||||
|
@ -10,7 +10,7 @@ constexpr auto TileWidth = 8;
|
||||
constexpr auto TileHeight = 8;
|
||||
constexpr auto PixelsPerTile = TileWidth * TileHeight;
|
||||
|
||||
constexpr auto FileExt_ng = ".ng";
|
||||
constexpr auto FileExt_npal = ".npal";
|
||||
constexpr auto FileExt_ng = "ng";
|
||||
constexpr auto FileExt_npal = "npal";
|
||||
|
||||
}
|
||||
|
@ -9,10 +9,22 @@
|
||||
#include <ox/std/buffer.hpp>
|
||||
|
||||
#include <nostalgia/foundation/context.hpp>
|
||||
#include <nostalgia/geo/size.hpp>
|
||||
|
||||
#include "event.hpp"
|
||||
#include "input.hpp"
|
||||
|
||||
namespace nostalgia::core::gl {
|
||||
void drawMainView(core::Context*) noexcept;
|
||||
void setRenderSize(core::Context*, int width, int height) noexcept;
|
||||
geo::Size getRenderSize(core::Context*) noexcept;
|
||||
void clearRenderSize(core::Context *ctx) noexcept;
|
||||
}
|
||||
|
||||
namespace nostalgia::core::renderer {
|
||||
ox::Error init(Context *ctx) noexcept;
|
||||
}
|
||||
|
||||
namespace nostalgia::geo {
|
||||
class Size;
|
||||
}
|
||||
@ -58,6 +70,7 @@ class Context: public foundation::Context {
|
||||
friend int getScreenHeight(Context *ctx) noexcept;
|
||||
friend int getScreenWidth(Context *ctx) noexcept;
|
||||
friend ox::Error initGfx(Context *ctx) noexcept;
|
||||
friend ox::Error renderer::init(Context *ctx) noexcept;
|
||||
friend ox::Error loadBgTileSheet(Context *ctx,
|
||||
unsigned cbb,
|
||||
const ox::FileAddress &tilesheetPath,
|
||||
@ -92,6 +105,10 @@ class Context: public foundation::Context {
|
||||
unsigned spriteSize,
|
||||
unsigned flipX) noexcept;
|
||||
friend void hideSprite(Context *ctx, unsigned idx) noexcept;
|
||||
friend void gl::drawMainView(core::Context*) noexcept;
|
||||
friend void gl::setRenderSize(core::Context*, int width, int height) noexcept;
|
||||
friend geo::Size gl::getRenderSize(core::Context*) noexcept;
|
||||
friend void gl::clearRenderSize(core::Context *ctx) noexcept;
|
||||
|
||||
public:
|
||||
ox::Vector<Drawer*, 5> drawers;
|
||||
|
@ -18,6 +18,12 @@
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
namespace gl {
|
||||
|
||||
void setMainViewEnabled(bool) noexcept;
|
||||
|
||||
}
|
||||
|
||||
extern ox::Array<char, 128> charMap;
|
||||
|
||||
class Drawer {
|
||||
|
@ -216,9 +216,7 @@ ox::Error initGfx(Context *ctx) noexcept {
|
||||
ImGui_ImplGlfw_InitForOpenGL(id->window, true);
|
||||
}
|
||||
themeImgui();
|
||||
void *rendererData = nullptr;
|
||||
oxReturnError(renderer::init(ctx, &rendererData));
|
||||
ctx->setRendererData(rendererData);
|
||||
oxReturnError(renderer::init(ctx));
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
|
@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include <nostalgia/core/core.hpp>
|
||||
#include <nostalgia/core/input.hpp>
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
ox::Result<ox::UniquePtr<Context>> init(ox::UniquePtr<ox::FileSystem>, ox::CRStringView) noexcept {
|
||||
return OxError(1);
|
||||
}
|
||||
|
||||
void setUpdateHandler(Context*, UpdateHandler) noexcept {
|
||||
}
|
||||
|
||||
uint64_t ticksMs(Context*) noexcept {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool buttonDown(Context*, Key) noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include <nostalgia/core/context.hpp>
|
||||
#include <nostalgia/core/gfx.hpp>
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
ox::Error initGfx(Context*) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
ox::Error shutdownGfx(Context*) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
void setWindowTitle(Context*, ox::CRStringView) noexcept {
|
||||
}
|
||||
|
||||
void focusWindow(Context*) noexcept {
|
||||
}
|
||||
|
||||
int getScreenWidth(Context*) noexcept {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getScreenHeight(Context*) noexcept {
|
||||
return 0;
|
||||
}
|
||||
|
||||
geo::Size getScreenSize(Context*) noexcept {
|
||||
return {0, 0};
|
||||
}
|
||||
|
||||
uint8_t bgStatus(Context*) noexcept {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void setBgStatus(Context*, uint32_t) noexcept {
|
||||
}
|
||||
|
||||
bool bgStatus(Context*, unsigned) noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
void setBgStatus(Context*, unsigned, bool) noexcept {
|
||||
}
|
||||
|
||||
// Do NOT rely on Context in the GBA version of this function.
|
||||
ox::Error initConsole(Context*) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
ox::Error loadBgTileSheet(Context*,
|
||||
int,
|
||||
const ox::FileAddress&,
|
||||
const ox::FileAddress&) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
ox::Error loadSpriteTileSheet(Context*,
|
||||
const ox::FileAddress&,
|
||||
const ox::FileAddress&) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
ox::Error loadBgPalette(Context*, int, const ox::FileAddress&) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
ox::Error loadSpritePalette(Context*, int, const ox::FileAddress&) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
// Do NOT use Context in the GBA version of this function.
|
||||
void puts(Context*, int, int, ox::CRStringView) noexcept {
|
||||
}
|
||||
|
||||
void setTile(Context*, int, int, int, uint8_t) noexcept {
|
||||
}
|
||||
|
||||
// Do NOT use Context in the GBA version of this function.
|
||||
void clearTileLayer(Context*, int) noexcept {
|
||||
}
|
||||
|
||||
[[maybe_unused]]
|
||||
void hideSprite(Context*, unsigned) noexcept {
|
||||
}
|
||||
|
||||
void setSprite(Context*,
|
||||
unsigned,
|
||||
int,
|
||||
int,
|
||||
unsigned,
|
||||
unsigned,
|
||||
unsigned,
|
||||
unsigned) noexcept {
|
||||
}
|
||||
|
||||
}
|
@ -14,8 +14,29 @@
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
class CoreModule: public foundation::Module {
|
||||
private:
|
||||
NostalgiaPaletteToPaletteConverter nostalgiaPaletteToPaletteConverter;
|
||||
TileSheetV1ToTileSheetConverter nostalgiaGraphicToTileSheetConverter;
|
||||
TileSheetToCompactTileSheetConverter tileSheetToCompactTileSheetConverter;
|
||||
TileSheetV2ToTileSheetConverter tileSheetV2ToTileSheetConverter;
|
||||
|
||||
public:
|
||||
static CoreModule mod;
|
||||
[[nodiscard]]
|
||||
ox::Vector<foundation::TypeDescGenerator> types() const noexcept override;
|
||||
[[nodiscard]]
|
||||
ox::Vector<const foundation::BaseConverter*> converters() const noexcept override;
|
||||
[[nodiscard]]
|
||||
ox::Vector<foundation::PackTransform> packTransforms() const noexcept override;
|
||||
};
|
||||
|
||||
CoreModule CoreModule::mod;
|
||||
|
||||
const foundation::Module *module() noexcept {
|
||||
return &CoreModule::mod;
|
||||
}
|
||||
|
||||
ox::Vector<foundation::TypeDescGenerator> CoreModule::types() const noexcept {
|
||||
return {
|
||||
foundation::generateTypeDesc<TileSheetV1>,
|
||||
|
@ -6,25 +6,8 @@
|
||||
|
||||
#include <nostalgia/foundation/module.hpp>
|
||||
|
||||
#include "typeconv.hpp"
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
class CoreModule: public foundation::Module {
|
||||
private:
|
||||
NostalgiaPaletteToPaletteConverter nostalgiaPaletteToPaletteConverter;
|
||||
TileSheetV1ToTileSheetConverter nostalgiaGraphicToTileSheetConverter;
|
||||
TileSheetToCompactTileSheetConverter tileSheetToCompactTileSheetConverter;
|
||||
TileSheetV2ToTileSheetConverter tileSheetV2ToTileSheetConverter;
|
||||
|
||||
public:
|
||||
static CoreModule mod;
|
||||
[[nodiscard]]
|
||||
ox::Vector<foundation::TypeDescGenerator> types() const noexcept override;
|
||||
[[nodiscard]]
|
||||
ox::Vector<const foundation::BaseConverter*> converters() const noexcept override;
|
||||
[[nodiscard]]
|
||||
ox::Vector<foundation::PackTransform> packTransforms() const noexcept override;
|
||||
};
|
||||
const foundation::Module *module() noexcept;
|
||||
|
||||
}
|
||||
|
@ -18,6 +18,16 @@ namespace nostalgia::core {
|
||||
|
||||
void ImGui_Impl_NewFrame() noexcept;
|
||||
|
||||
namespace gl {
|
||||
|
||||
static bool mainViewEnabled = true;
|
||||
|
||||
void setMainViewEnabled(bool enabled) noexcept {
|
||||
mainViewEnabled = enabled;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace renderer {
|
||||
|
||||
constexpr uint64_t TileRows = 128;
|
||||
@ -67,6 +77,7 @@ struct GlImplData {
|
||||
SpriteBlockset spriteBlocks;
|
||||
ox::Array<Sprite, 128> spriteStates;
|
||||
ox::Array<Background, 4> backgrounds;
|
||||
ox::Optional<geo::Size> renderSize;
|
||||
};
|
||||
|
||||
constexpr ox::StringView bgvshadTmpl = R"(
|
||||
@ -74,9 +85,13 @@ constexpr ox::StringView bgvshadTmpl = R"(
|
||||
in vec2 vTexCoord;
|
||||
in vec2 vPosition;
|
||||
out vec2 fTexCoord;
|
||||
uniform float vXScale;
|
||||
uniform float vTileHeight;
|
||||
void main() {
|
||||
gl_Position = vec4(vPosition, 0.0, 1.0);
|
||||
float xScaleInvert = 1.0 - vXScale;
|
||||
gl_Position = vec4(
|
||||
vPosition.x * vXScale - xScaleInvert, vPosition.y,
|
||||
0.0, 1.0);
|
||||
fTexCoord = vTexCoord * vec2(1, vTileHeight);
|
||||
})";
|
||||
|
||||
@ -98,9 +113,13 @@ constexpr ox::StringView spritevshadTmpl = R"(
|
||||
in vec2 vTexCoord;
|
||||
in vec2 vPosition;
|
||||
out vec2 fTexCoord;
|
||||
uniform float vXScale;
|
||||
uniform float vTileHeight;
|
||||
void main() {
|
||||
gl_Position = vec4(vPosition, 0.0, 1.0);
|
||||
float xScaleInvert = 1.0 - vXScale;
|
||||
gl_Position = vec4(
|
||||
vPosition.x * vXScale - xScaleInvert, vPosition.y,
|
||||
0.0, 1.0);
|
||||
fTexCoord = vTexCoord * vec2(1, vTileHeight) * vec2(vEnabled, vEnabled);
|
||||
})";
|
||||
|
||||
@ -111,7 +130,7 @@ static constexpr auto bgVertexRow(unsigned x, unsigned y) noexcept {
|
||||
return y * TileRows + x;
|
||||
}
|
||||
|
||||
static void setSpriteBufferObject(Context *ctx,
|
||||
static void setSpriteBufferObject(Context*,
|
||||
unsigned vi,
|
||||
float enabled,
|
||||
float x, float y,
|
||||
@ -120,9 +139,8 @@ static void setSpriteBufferObject(Context *ctx,
|
||||
float *vbo,
|
||||
GLuint *ebo) noexcept {
|
||||
// don't worry, this memcpy gets optimized to something much more ideal
|
||||
const auto [sw, sh] = getScreenSize(ctx);
|
||||
constexpr float xmod = 0.1f;
|
||||
constexpr float ymod = 0.1f;
|
||||
const auto xmod = ymod * static_cast<float>(sh) / static_cast<float>(sw);
|
||||
x *= xmod;
|
||||
y *= -ymod;
|
||||
x -= 1.f;
|
||||
@ -144,7 +162,7 @@ static void setSpriteBufferObject(Context *ctx,
|
||||
memcpy(ebo, elms.data(), sizeof(elms));
|
||||
}
|
||||
|
||||
static void setTileBufferObject(Context *ctx,
|
||||
static void setTileBufferObject(Context*,
|
||||
unsigned vi,
|
||||
float x,
|
||||
float y,
|
||||
@ -152,9 +170,8 @@ static void setTileBufferObject(Context *ctx,
|
||||
float *vbo,
|
||||
GLuint *ebo) noexcept {
|
||||
// don't worry, this memcpy gets optimized to something much more ideal
|
||||
const auto [sw, sh] = getScreenSize(ctx);
|
||||
constexpr float ymod = 2.0f / 20.0f;
|
||||
const float xmod = ymod * static_cast<float>(sh) / static_cast<float>(sw);
|
||||
constexpr float ymod = 0.1f;
|
||||
constexpr float xmod = 0.1f;
|
||||
x *= xmod;
|
||||
y *= -ymod;
|
||||
x -= 1.0f;
|
||||
@ -279,11 +296,15 @@ static void drawBackground(CBB *cbb) noexcept {
|
||||
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(cbb->elements.size()), GL_UNSIGNED_INT, nullptr);
|
||||
}
|
||||
|
||||
static void drawBackgrounds(GlImplData *id) noexcept {
|
||||
static void drawBackgrounds(core::Context *ctx, GlImplData *id) noexcept {
|
||||
// load background shader and its uniforms
|
||||
glUseProgram(id->bgShader);
|
||||
const auto uniformXScale = static_cast<GLint>(glGetUniformLocation(id->bgShader, "vXScale"));
|
||||
const auto uniformTileHeight = static_cast<GLint>(glGetUniformLocation(id->bgShader, "vTileHeight"));
|
||||
//glUniform3fv(uniformPalette, GlImplData::ColorCnt, id->palette.data());
|
||||
const auto [wi, hi] = gl::getRenderSize(ctx);
|
||||
const auto wf = static_cast<float>(wi);
|
||||
const auto hf = static_cast<float>(hi);
|
||||
glUniform1f(uniformXScale, hf / wf);
|
||||
for (const auto &bg : id->backgrounds) {
|
||||
if (bg.enabled) {
|
||||
auto &cbb = id->cbbs[bg.cbbIdx];
|
||||
@ -294,10 +315,15 @@ static void drawBackgrounds(GlImplData *id) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
static void drawSprites(GlImplData *id) noexcept {
|
||||
static void drawSprites(core::Context *ctx, GlImplData *id) noexcept {
|
||||
glUseProgram(id->spriteShader);
|
||||
auto &sb = id->spriteBlocks;
|
||||
const auto uniformXScale = static_cast<GLint>(glGetUniformLocation(id->bgShader, "vXScale"));
|
||||
const auto uniformTileHeight = static_cast<GLint>(glGetUniformLocation(id->spriteShader, "vTileHeight"));
|
||||
const auto [wi, hi] = gl::getRenderSize(ctx);
|
||||
const auto wf = static_cast<float>(wi);
|
||||
const auto hf = static_cast<float>(hi);
|
||||
glUniform1f(uniformXScale, hf / wf);
|
||||
// update vbo
|
||||
glBindVertexArray(sb.vao);
|
||||
if (sb.updated) {
|
||||
@ -312,7 +338,7 @@ static void drawSprites(GlImplData *id) noexcept {
|
||||
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(sb.elements.size()), GL_UNSIGNED_INT, nullptr);
|
||||
}
|
||||
|
||||
ox::Error init(Context *ctx, void **rendererData) noexcept {
|
||||
ox::Error init(Context *ctx) noexcept {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
const auto bgVshad = ox::sfmt(bgvshadTmpl, glutils::GlslVersion);
|
||||
@ -320,7 +346,7 @@ ox::Error init(Context *ctx, void **rendererData) noexcept {
|
||||
const auto spriteVshad = ox::sfmt(spritevshadTmpl, glutils::GlslVersion);
|
||||
const auto spriteFshad = ox::sfmt(spritefshadTmpl, glutils::GlslVersion);
|
||||
const auto id = ox::make<GlImplData>();
|
||||
*rendererData = id;
|
||||
ctx->setRendererData(id);
|
||||
oxReturnError(glutils::buildShaderProgram(bgVshad.c_str(), bgFshad.c_str()).moveTo(&id->bgShader));
|
||||
oxReturnError(glutils::buildShaderProgram(spriteVshad.c_str(), spriteFshad.c_str()).moveTo(&id->spriteShader));
|
||||
for (auto &bg : id->cbbs) {
|
||||
@ -328,7 +354,7 @@ ox::Error init(Context *ctx, void **rendererData) noexcept {
|
||||
}
|
||||
initSpritesBufferset(ctx, id->spriteShader, &id->spriteBlocks);
|
||||
ImGui_ImplOpenGL3_Init(glutils::GlslVersion);
|
||||
return OxError(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
void shutdown(Context*, void *rendererData) noexcept {
|
||||
@ -422,9 +448,8 @@ void draw(Context *ctx) noexcept {
|
||||
glClearColor(0, 0, 0, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
// render
|
||||
renderer::drawBackgrounds(id);
|
||||
if (id->spriteBlocks.tex) {
|
||||
renderer::drawSprites(id);
|
||||
if (gl::mainViewEnabled) {
|
||||
gl::drawMainView(ctx);
|
||||
}
|
||||
for (const auto cd : ctx->drawers) {
|
||||
cd->draw(ctx);
|
||||
@ -530,4 +555,35 @@ void setTile(Context *ctx, unsigned bgIdx, int column, int row, uint8_t tile) no
|
||||
bg.updated = true;
|
||||
}
|
||||
|
||||
namespace gl {
|
||||
|
||||
void drawMainView(core::Context *ctx) noexcept {
|
||||
const auto id = ctx->rendererData<renderer::GlImplData>();
|
||||
renderer::drawBackgrounds(ctx, id);
|
||||
if (id->spriteBlocks.tex) {
|
||||
renderer::drawSprites(ctx, id);
|
||||
}
|
||||
}
|
||||
|
||||
void setRenderSize(core::Context *ctx, int width, int height) noexcept {
|
||||
const auto id = ctx->rendererData<renderer::GlImplData>();
|
||||
id->renderSize.emplace(width, height);
|
||||
}
|
||||
|
||||
void clearRenderSize(core::Context *ctx) noexcept {
|
||||
auto id = ctx->rendererData<renderer::GlImplData>();
|
||||
id->renderSize.reset();
|
||||
}
|
||||
|
||||
geo::Size getRenderSize(core::Context *ctx) noexcept {
|
||||
const auto id = ctx->rendererData<renderer::GlImplData>();
|
||||
if (id->renderSize.has_value()) {
|
||||
return id->renderSize.value();
|
||||
} else {
|
||||
return core::getScreenSize(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -11,19 +11,20 @@ ox::Result<ox::UUID> readUuidHeader(const ox::Buffer &buff) noexcept {
|
||||
}
|
||||
|
||||
ox::Result<ox::UUID> readUuidHeader(const char *buff, std::size_t buffLen) noexcept {
|
||||
if (buffLen < 40) {
|
||||
return OxError(1, "Insufficient data contain complete Nostalgia header");
|
||||
if (buffLen < N1HdrSz) {
|
||||
return OxError(1, "Insufficient data to contain complete Nostalgia header");
|
||||
}
|
||||
if (ox_memcmp(buff, "N1;", 3) != 0) {
|
||||
return OxError(2, "No Nostalgia header data");
|
||||
ox::StringView n1Hdr = "N1;";
|
||||
if (n1Hdr == buff) {
|
||||
return OxError(2, "No Nostalgia asset header data");
|
||||
}
|
||||
return ox::UUID::fromString(ox::StringView(buff + 3, 36));
|
||||
return ox::UUID::fromString(ox::StringView(buff + n1Hdr.bytes(), 36));
|
||||
}
|
||||
|
||||
ox::Result<ox::ModelObject> readAsset(ox::TypeStore *ts, const ox::Buffer &buff) noexcept {
|
||||
std::size_t offset = 0;
|
||||
if (!readUuidHeader(buff).error) {
|
||||
offset = 40; // the size of N1 headers
|
||||
offset = N1HdrSz;
|
||||
}
|
||||
return ox::readClaw(ts, buff.data() + offset, buff.size() - offset);
|
||||
}
|
||||
@ -31,7 +32,7 @@ ox::Result<ox::ModelObject> readAsset(ox::TypeStore *ts, const ox::Buffer &buff)
|
||||
ox::Result<AssetHdr> readAssetHeader(const char *buff, std::size_t buffLen) noexcept {
|
||||
AssetHdr out;
|
||||
const auto err = readUuidHeader(buff, buffLen).moveTo(&out.uuid);
|
||||
const auto offset = err ? 0 : 40;
|
||||
const auto offset = err ? 0 : N1HdrSz;
|
||||
buff = buff + offset;
|
||||
buffLen = buffLen - offset;
|
||||
oxReturnError(ox::readClawHeader(buff, buffLen).moveTo(&out.clawHdr));
|
||||
|
@ -9,17 +9,16 @@
|
||||
#include <ox/claw/claw.hpp>
|
||||
#include <ox/fs/fs.hpp>
|
||||
|
||||
#include <nostalgia/foundation/context.hpp>
|
||||
|
||||
namespace nostalgia::foundation {
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto N1HdrSz = 40;
|
||||
|
||||
ox::Result<ox::UUID> readUuidHeader(const ox::Buffer &buff) noexcept;
|
||||
|
||||
ox::Result<ox::UUID> readUuidHeader(const char *buff, std::size_t buffLen) noexcept;
|
||||
|
||||
ox::Error writeUuidHeader(ox::Writer_c auto *writer, const ox::UUID &uuid) noexcept {
|
||||
const auto hdr = ox::sfmt<ox::BString<40>>("N1;{};", uuid.toString());
|
||||
const auto hdr = ox::sfmt<ox::BString<N1HdrSz>>("N1;{};", uuid.toString());
|
||||
return write(writer, hdr);
|
||||
}
|
||||
|
||||
@ -28,7 +27,7 @@ ox::Result<T> readAsset(const ox::Buffer &buff) noexcept {
|
||||
std::size_t offset = 0;
|
||||
const auto err = readUuidHeader(buff).error;
|
||||
if (!err) {
|
||||
offset = 40; // the size of N1 headers
|
||||
offset = N1HdrSz; // the size of N1 headers
|
||||
}
|
||||
return ox::readClaw<T>(buff.data() + offset, buff.size() - offset);
|
||||
}
|
||||
|
@ -41,10 +41,12 @@ class AssetContainer {
|
||||
AssetContainer& operator=(AssetContainer&) = delete;
|
||||
AssetContainer& operator=(AssetContainer&&) = delete;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr T *get() noexcept {
|
||||
return &m_obj;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const T *get() const noexcept {
|
||||
return &m_obj;
|
||||
}
|
||||
@ -66,6 +68,7 @@ class AssetContainer {
|
||||
--m_references;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr int references() const noexcept {
|
||||
return m_references;
|
||||
}
|
||||
@ -92,6 +95,7 @@ class AssetRef: public ox::SignalHandler {
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const T *get() const noexcept {
|
||||
if (m_ctr) {
|
||||
return m_ctr->get();
|
||||
|
@ -17,9 +17,8 @@ ox::Result<ox::UPtr<Ctx>> init(ox::UPtr<ox::FileSystem> &&fs, ox::CRStringView a
|
||||
auto ctx = ox::make_unique<Ctx>();
|
||||
ctx->appName = appName;
|
||||
oxIgnoreError(setRomFs(ctx.get(), std::move(fs)));
|
||||
auto mods = modules();
|
||||
if (mods) {
|
||||
for (auto &mod : *mods) {
|
||||
const auto &mods = modules();
|
||||
for (auto &mod : mods) {
|
||||
// register type converters
|
||||
for (auto c : mod->converters()) {
|
||||
ctx->converters.emplace_back(c);
|
||||
@ -29,7 +28,6 @@ ox::Result<ox::UPtr<Ctx>> init(ox::UPtr<ox::FileSystem> &&fs, ox::CRStringView a
|
||||
ctx->packTransforms.emplace_back(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
@ -13,8 +13,8 @@ void registerModule(const Module *mod) noexcept {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
const ox::Vector<const Module*> *modules() noexcept {
|
||||
return &mods;
|
||||
const ox::Vector<const Module*> &modules() noexcept {
|
||||
return mods;
|
||||
}
|
||||
|
||||
|
||||
|
@ -38,6 +38,6 @@ class Module {
|
||||
void registerModule(const Module *mod) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
const ox::Vector<const foundation::Module*> *modules() noexcept;
|
||||
const ox::Vector<const foundation::Module*> &modules() noexcept;
|
||||
|
||||
}
|
||||
|
@ -176,7 +176,7 @@ ox::Result<ox::Buffer> convertBuffToBuff(foundation::Context *ctx, const ox::Buf
|
||||
}
|
||||
|
||||
template<typename From, typename To, ox::ClawFormat fmt = ox::ClawFormat::Metal>
|
||||
auto transformRule(foundation::Context *ctx, ox::Buffer *buff) -> ox::Error {
|
||||
auto transformRule(foundation::Context *ctx, ox::Buffer *buff) noexcept -> ox::Error {
|
||||
oxRequire(hdr, readAssetHeader(*buff));
|
||||
const auto typeId = ox::buildTypeId(
|
||||
hdr.clawHdr.typeName, hdr.clawHdr.typeVersion, hdr.clawHdr.typeParams);
|
||||
|
@ -3,7 +3,6 @@
|
||||
*/
|
||||
|
||||
#include <nostalgia/core/core.hpp>
|
||||
#include <nostalgia/foundation/media.hpp>
|
||||
#include <nostalgia/scene/scene.hpp>
|
||||
|
||||
using namespace nostalgia;
|
||||
@ -37,7 +36,7 @@ ox::Error run(ox::UniquePtr<ox::FileSystem> fs) noexcept {
|
||||
oxRequire(scn, foundation::readObj<scene::SceneStatic>(ctx.get(), SceneAddr));
|
||||
core::setUpdateHandler(ctx.get(), updateHandler);
|
||||
core::setKeyEventHandler(ctx.get(), keyEventHandler);
|
||||
s_scene.emplace(scn.get());
|
||||
s_scene.emplace(*scn);
|
||||
oxReturnError(s_scene->setupDisplay(ctx.get()));
|
||||
return core::run(ctx.get());
|
||||
}
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include <ox/logconn/logconn.hpp>
|
||||
|
||||
#include <nostalgia/core/core.hpp>
|
||||
#include <nostalgia/foundation/media.hpp>
|
||||
|
||||
#include <nostalgia/appmodules/appmodules.hpp>
|
||||
|
||||
|
@ -22,6 +22,6 @@ install(
|
||||
include/nostalgia/scene
|
||||
)
|
||||
|
||||
#if(NOSTALGIA_BUILD_STUDIO)
|
||||
# add_subdirectory(studio)
|
||||
#endif()
|
||||
if(NOSTALGIA_BUILD_STUDIO)
|
||||
add_subdirectory(studio)
|
||||
endif()
|
||||
|
@ -8,25 +8,25 @@
|
||||
|
||||
namespace nostalgia::scene {
|
||||
|
||||
Scene::Scene(const SceneStatic *sceneStatic) noexcept:
|
||||
Scene::Scene(const SceneStatic &sceneStatic) noexcept:
|
||||
m_sceneStatic(sceneStatic) {
|
||||
}
|
||||
|
||||
ox::Error Scene::setupDisplay(core::Context *ctx) noexcept {
|
||||
if (m_sceneStatic->palettes.empty()) {
|
||||
if (m_sceneStatic.palettes.empty()) {
|
||||
return OxError(1, "Scene has no palettes");
|
||||
}
|
||||
const auto &palette = m_sceneStatic->palettes[0];
|
||||
const auto &palette = m_sceneStatic.palettes[0];
|
||||
oxReturnError(core::loadBgTileSheet(
|
||||
ctx, 0, m_sceneStatic->tilesheet, palette));
|
||||
ctx, 0, m_sceneStatic.tilesheet, palette));
|
||||
// disable all backgrounds
|
||||
core::setBgStatus(ctx, 0);
|
||||
for (auto layerNo = 0u; const auto &layer : m_sceneStatic->tileMapIdx) {
|
||||
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];
|
||||
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);
|
||||
|
@ -10,10 +10,10 @@ namespace nostalgia::scene {
|
||||
|
||||
class Scene {
|
||||
private:
|
||||
const SceneStatic *m_sceneStatic = nullptr;
|
||||
const SceneStatic &m_sceneStatic;
|
||||
|
||||
public:
|
||||
explicit Scene(const SceneStatic *sceneStatic) noexcept;
|
||||
explicit Scene(const SceneStatic &sceneStatic) noexcept;
|
||||
|
||||
ox::Error setupDisplay(core::Context *ctx) noexcept;
|
||||
|
||||
|
@ -5,29 +5,44 @@
|
||||
#include <ox/model/model.hpp>
|
||||
|
||||
#include "scenestatic.hpp"
|
||||
#include "typeconv.hpp"
|
||||
|
||||
#include "scenemodule.hpp"
|
||||
|
||||
namespace nostalgia::scene {
|
||||
|
||||
SceneModule SceneModule::mod;
|
||||
class SceneModule: public foundation::Module {
|
||||
private:
|
||||
SceneDocToSceneStaticConverter sceneDocToSceneStaticConverter;
|
||||
|
||||
ox::Vector<foundation::TypeDescGenerator> SceneModule::types() const noexcept {
|
||||
public:
|
||||
[[nodiscard]]
|
||||
ox::Vector<foundation::TypeDescGenerator> types() const noexcept override {
|
||||
return {
|
||||
foundation::generateTypeDesc<SceneDoc>,
|
||||
foundation::generateTypeDesc<SceneStatic>,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
ox::Vector<const foundation::BaseConverter*> SceneModule::converters() const noexcept {
|
||||
[[nodiscard]]
|
||||
ox::Vector<const foundation::BaseConverter*> converters() const noexcept override {
|
||||
return {
|
||||
&sceneDocToSceneStaticConverter,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
ox::Vector<foundation::PackTransform> SceneModule::packTransforms() const noexcept {
|
||||
[[nodiscard]]
|
||||
ox::Vector<foundation::PackTransform> packTransforms() const noexcept override {
|
||||
return {
|
||||
foundation::transformRule<SceneDoc, SceneStatic>,
|
||||
};
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
static SceneModule mod;
|
||||
const foundation::Module *module() noexcept {
|
||||
return &mod;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,22 +6,8 @@
|
||||
|
||||
#include <nostalgia/foundation/module.hpp>
|
||||
|
||||
#include "typeconv.hpp"
|
||||
|
||||
namespace nostalgia::scene {
|
||||
|
||||
class SceneModule: public foundation::Module {
|
||||
private:
|
||||
SceneDocToSceneStaticConverter sceneDocToSceneStaticConverter;
|
||||
|
||||
public:
|
||||
static SceneModule mod;
|
||||
[[nodiscard]]
|
||||
ox::Vector<foundation::TypeDescGenerator> types() const noexcept override;
|
||||
[[nodiscard]]
|
||||
ox::Vector<const foundation::BaseConverter*> converters() const noexcept override;
|
||||
[[nodiscard]]
|
||||
ox::Vector<foundation::PackTransform> packTransforms() const noexcept override;
|
||||
};
|
||||
const foundation::Module *module() noexcept;
|
||||
|
||||
}
|
||||
|
@ -14,6 +14,17 @@
|
||||
|
||||
namespace nostalgia::scene {
|
||||
|
||||
struct SpriteDoc {
|
||||
|
||||
constexpr static auto TypeName = "net.drinkingtea.nostalgia.scene.SpriteDoc";
|
||||
constexpr static auto TypeVersion = 1;
|
||||
constexpr static auto Preloadable = true;
|
||||
|
||||
ox::String tilesheetPath;
|
||||
ox::Vector<core::SubSheetId> subsheetId;
|
||||
|
||||
};
|
||||
|
||||
struct TileDoc {
|
||||
|
||||
constexpr static auto TypeName = "net.drinkingtea.nostalgia.scene.TileDoc";
|
||||
@ -23,6 +34,7 @@ struct TileDoc {
|
||||
core::SubSheetId subsheetId = -1;
|
||||
ox::String subsheetPath;
|
||||
uint8_t type = 0;
|
||||
ox::Array<uint8_t, 4> layerAttachments;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr ox::Result<core::SubSheetId> getSubsheetId(const core::TileSheet &ts) const noexcept {
|
||||
@ -88,6 +100,38 @@ oxModelBegin(SceneDoc)
|
||||
oxModelField(tiles)
|
||||
oxModelEnd()
|
||||
|
||||
|
||||
constexpr void setTopEdge(uint8_t &layerAttachments, unsigned val) noexcept {
|
||||
layerAttachments = (layerAttachments & 0b11111100) | val;
|
||||
}
|
||||
constexpr void setBottomEdge(uint8_t &layerAttachments, unsigned val) noexcept {
|
||||
layerAttachments = (layerAttachments & 0b11110011) | (val << 2);
|
||||
}
|
||||
constexpr void setLeftEdge(uint8_t &layerAttachments, unsigned val) noexcept {
|
||||
layerAttachments = (layerAttachments & 0b11001111) | (val << 4);
|
||||
}
|
||||
constexpr void setRightEdge(uint8_t &layerAttachments, unsigned val) noexcept {
|
||||
layerAttachments = (layerAttachments & 0b00111111) | (val << 6);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr unsigned topEdge(uint8_t layerAttachments) noexcept {
|
||||
return layerAttachments & 0b11;
|
||||
}
|
||||
[[nodiscard]]
|
||||
constexpr unsigned bottomEdge(uint8_t layerAttachments) noexcept {
|
||||
return (layerAttachments >> 2) & 0b11;
|
||||
}
|
||||
[[nodiscard]]
|
||||
constexpr unsigned leftEdge(uint8_t layerAttachments) noexcept {
|
||||
return (layerAttachments >> 4) & 0b11;
|
||||
}
|
||||
[[nodiscard]]
|
||||
constexpr unsigned rightEdge(uint8_t layerAttachments) noexcept {
|
||||
return (layerAttachments >> 6) & 0b11;
|
||||
}
|
||||
|
||||
|
||||
struct SceneStatic {
|
||||
|
||||
constexpr static auto TypeName = "net.drinkingtea.nostalgia.scene.SceneStatic";
|
||||
@ -97,9 +141,11 @@ struct SceneStatic {
|
||||
struct Tile {
|
||||
uint16_t &tileMapIdx;
|
||||
uint8_t &tileType;
|
||||
constexpr Tile(uint16_t *pTileMapIdx, uint8_t *pTileType) noexcept:
|
||||
tileMapIdx(*pTileMapIdx),
|
||||
tileType(*pTileType) {
|
||||
uint8_t &layerAttachments;
|
||||
constexpr Tile(uint16_t &pTileMapIdx, uint8_t &pTileType, uint8_t &pLayerAttachments) noexcept:
|
||||
tileMapIdx(pTileMapIdx),
|
||||
tileType(pTileType),
|
||||
layerAttachments(pLayerAttachments) {
|
||||
}
|
||||
};
|
||||
struct Layer {
|
||||
@ -107,19 +153,22 @@ struct SceneStatic {
|
||||
uint16_t &rows;
|
||||
ox::Vector<uint16_t> &tileMapIdx;
|
||||
ox::Vector<uint8_t> &tileType;
|
||||
ox::Vector<uint8_t> &layerAttachments;
|
||||
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) {
|
||||
uint16_t &pColumns,
|
||||
uint16_t &pRows,
|
||||
ox::Vector<uint16_t> &pTileMapIdx,
|
||||
ox::Vector<uint8_t> &pTileType,
|
||||
ox::Vector<uint8_t> &pLayerAttachments) noexcept:
|
||||
columns(pColumns),
|
||||
rows(pRows),
|
||||
tileMapIdx(pTileMapIdx),
|
||||
tileType(pTileType),
|
||||
layerAttachments(pLayerAttachments) {
|
||||
}
|
||||
[[nodiscard]]
|
||||
constexpr Tile tile(std::size_t i) noexcept {
|
||||
return {&tileMapIdx[i], &tileType[i]};
|
||||
return {tileMapIdx[i], tileType[i], layerAttachments[i]};
|
||||
}
|
||||
constexpr auto setDimensions(geo::Size dim) noexcept {
|
||||
columns = dim.width;
|
||||
@ -127,6 +176,7 @@ struct SceneStatic {
|
||||
const auto tileCnt = static_cast<unsigned>(columns * rows);
|
||||
tileMapIdx.resize(tileCnt);
|
||||
tileType.resize(tileCnt);
|
||||
layerAttachments.resize(tileCnt);
|
||||
}
|
||||
};
|
||||
|
||||
@ -137,13 +187,21 @@ struct SceneStatic {
|
||||
ox::Vector<uint16_t> rows;
|
||||
ox::Vector<ox::Vector<uint16_t>> tileMapIdx;
|
||||
ox::Vector<ox::Vector<uint8_t>> tileType;
|
||||
ox::Vector<ox::Vector<uint8_t>> layerAttachments;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr Layer layer(std::size_t i) noexcept {
|
||||
return {&columns[i], &rows[i], &tileMapIdx[i], &tileType[i]};
|
||||
return {
|
||||
columns[i],
|
||||
rows[i],
|
||||
tileMapIdx[i],
|
||||
tileType[i],
|
||||
layerAttachments[i],
|
||||
};
|
||||
}
|
||||
|
||||
constexpr auto setLayerCnt(std::size_t layerCnt) noexcept {
|
||||
this->layerAttachments.resize(layerCnt);
|
||||
this->columns.resize(layerCnt);
|
||||
this->rows.resize(layerCnt);
|
||||
this->tileMapIdx.resize(layerCnt);
|
||||
@ -157,8 +215,9 @@ oxModelBegin(SceneStatic)
|
||||
oxModelField(palettes)
|
||||
oxModelField(columns)
|
||||
oxModelField(rows)
|
||||
oxModelFieldRename(tile_map_idx, tileMapIdx)
|
||||
oxModelFieldRename(tile_type, tileType)
|
||||
oxModelField(tileMapIdx)
|
||||
oxModelField(tileType)
|
||||
oxModelField(layerAttachments)
|
||||
oxModelEnd()
|
||||
|
||||
}
|
||||
|
@ -9,6 +9,30 @@
|
||||
|
||||
namespace nostalgia::scene {
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr unsigned adjustLayerAttachment(unsigned layer, unsigned attachment) noexcept {
|
||||
if (attachment == 0) {
|
||||
return layer;
|
||||
} else {
|
||||
return attachment - 1;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr void setLayerAttachments(unsigned layer, const TileDoc &srcTile, SceneStatic::Tile &dstTile) noexcept {
|
||||
setTopEdge(
|
||||
dstTile.layerAttachments,
|
||||
adjustLayerAttachment(layer, srcTile.layerAttachments[0]));
|
||||
setBottomEdge(
|
||||
dstTile.layerAttachments,
|
||||
adjustLayerAttachment(layer, srcTile.layerAttachments[1]));
|
||||
setLeftEdge(
|
||||
dstTile.layerAttachments,
|
||||
adjustLayerAttachment(layer, srcTile.layerAttachments[2]));
|
||||
setRightEdge(
|
||||
dstTile.layerAttachments,
|
||||
adjustLayerAttachment(layer, srcTile.layerAttachments[3]));
|
||||
}
|
||||
|
||||
ox::Error SceneDocToSceneStaticConverter::convert(
|
||||
foundation::Context *ctx,
|
||||
SceneDoc *src,
|
||||
@ -32,6 +56,7 @@ ox::Error SceneDocToSceneStaticConverter::convert(
|
||||
oxRequire(path, srcTile.getSubsheetPath(*ts));
|
||||
oxRequire(mapIdx, ts->getTileOffset(path));
|
||||
dstTile.tileMapIdx = static_cast<uint16_t>(mapIdx);
|
||||
setLayerAttachments(layerIdx, srcTile, dstTile);
|
||||
++tileIdx;
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ target_link_libraries(
|
||||
NostalgiaAppModules
|
||||
NostalgiaStudio
|
||||
NostalgiaCore-Studio
|
||||
NostalgiaScene-Studio
|
||||
)
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Release" AND NOT WIN32)
|
||||
|
@ -7,13 +7,17 @@
|
||||
#include <ox/std/memory.hpp>
|
||||
|
||||
#include <nostalgia/core/studio/module.hpp>
|
||||
#include <nostalgia/scene/studio/module.hpp>
|
||||
|
||||
namespace nostalgia {
|
||||
|
||||
[[maybe_unused]] // GCC warns about the existence of this "unused" constexpr list in a header file...
|
||||
constexpr auto BuiltinModules = {
|
||||
[] {
|
||||
return ox::make_unique<core::StudioModule>();
|
||||
[[maybe_unused]] // GCC warns about the existence of this "unused" inline list in a header file...
|
||||
inline ox::Vector<std::function<ox::UPtr<studio::Module>()>, 2> BuiltinModules = {
|
||||
[]() -> ox::UPtr<studio::Module> {
|
||||
return ox::UPtr<studio::Module>(new core::StudioModule());
|
||||
},
|
||||
[]() -> ox::UPtr<studio::Module> {
|
||||
return ox::UPtr<studio::Module>(new scene::StudioModule());
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -23,7 +23,7 @@ constexpr auto ConfigDir = [] {
|
||||
}
|
||||
}();
|
||||
|
||||
ox::String configPath(const core::Context *ctx) noexcept {
|
||||
ox::String configPath(const foundation::Context *ctx) noexcept {
|
||||
const auto homeDir = std::getenv(ox::defines::OS == ox::OS::Windows ? "USERPROFILE" : "HOME");
|
||||
return ox::sfmt(ConfigDir, homeDir, ctx->appName);
|
||||
}
|
||||
|
@ -18,10 +18,10 @@
|
||||
namespace nostalgia::studio {
|
||||
|
||||
[[nodiscard]]
|
||||
ox::String configPath(const core::Context *ctx) noexcept;
|
||||
ox::String configPath(const foundation::Context *ctx) noexcept;
|
||||
|
||||
template<typename T>
|
||||
ox::Result<T> readConfig(core::Context *ctx, ox::CRStringView name) noexcept {
|
||||
ox::Result<T> readConfig(foundation::Context *ctx, ox::CRStringView name) noexcept {
|
||||
oxAssert(name != "", "Config type has no TypeName");
|
||||
const auto path = ox::sfmt("/{}.json", name);
|
||||
ox::PassThroughFS fs(configPath(ctx));
|
||||
@ -34,13 +34,13 @@ ox::Result<T> readConfig(core::Context *ctx, ox::CRStringView name) noexcept {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ox::Result<T> readConfig(core::Context *ctx) noexcept {
|
||||
ox::Result<T> readConfig(foundation::Context *ctx) noexcept {
|
||||
constexpr auto TypeName = ox::requireModelTypeName<T>();
|
||||
return readConfig<T>(ctx, TypeName);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ox::Error writeConfig(core::Context *ctx, ox::CRStringView name, T *data) noexcept {
|
||||
ox::Error writeConfig(foundation::Context *ctx, ox::CRStringView name, T *data) noexcept {
|
||||
oxAssert(name != "", "Config type has no TypeName");
|
||||
const auto path = ox::sfmt("/{}.json", name);
|
||||
ox::PassThroughFS fs(configPath(ctx));
|
||||
@ -58,13 +58,13 @@ ox::Error writeConfig(core::Context *ctx, ox::CRStringView name, T *data) noexce
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ox::Error writeConfig(core::Context *ctx, T *data) noexcept {
|
||||
ox::Error writeConfig(foundation::Context *ctx, T *data) noexcept {
|
||||
constexpr auto TypeName = ox::requireModelTypeName<T>();
|
||||
return writeConfig(ctx, TypeName, data);
|
||||
}
|
||||
|
||||
template<typename T, typename Func>
|
||||
void openConfig(core::Context *ctx, const auto &name, Func f) noexcept {
|
||||
void openConfig(foundation::Context *ctx, const auto &name, Func f) noexcept {
|
||||
oxAssert(name != "", "Config type has no TypeName");
|
||||
const auto [c, err] = readConfig<T>(ctx, name);
|
||||
oxLogError(err);
|
||||
@ -72,13 +72,13 @@ void openConfig(core::Context *ctx, const auto &name, Func f) noexcept {
|
||||
}
|
||||
|
||||
template<typename T, typename Func>
|
||||
void openConfig(core::Context *ctx, Func f) noexcept {
|
||||
void openConfig(foundation::Context *ctx, Func f) noexcept {
|
||||
constexpr auto TypeName = ox::requireModelTypeName<T>();
|
||||
openConfig<T>(ctx, TypeName, f);
|
||||
}
|
||||
|
||||
template<typename T, typename Func>
|
||||
void editConfig(core::Context *ctx, const auto &name, Func f) noexcept {
|
||||
void editConfig(foundation::Context *ctx, const auto &name, Func f) noexcept {
|
||||
oxAssert(ox_strcmp(name, ""), "Config type has no TypeName");
|
||||
auto [c, err] = readConfig<T>(ctx, name);
|
||||
oxLogError(err);
|
||||
@ -87,7 +87,7 @@ void editConfig(core::Context *ctx, const auto &name, Func f) noexcept {
|
||||
}
|
||||
|
||||
template<typename T, typename Func>
|
||||
void editConfig(core::Context *ctx, Func f) noexcept {
|
||||
void editConfig(foundation::Context *ctx, Func f) noexcept {
|
||||
constexpr auto TypeName = ox::requireModelTypeName<T>();
|
||||
editConfig<T>(ctx, TypeName, f);
|
||||
}
|
||||
|
@ -29,6 +29,13 @@ void BaseEditor::exportFile() {
|
||||
void BaseEditor::keyStateChanged(core::Key, bool) {
|
||||
}
|
||||
|
||||
void BaseEditor::onActivated() noexcept {
|
||||
}
|
||||
|
||||
bool BaseEditor::requiresConstantRefresh() const noexcept {
|
||||
return m_requiresConstantRefresh;
|
||||
}
|
||||
|
||||
void BaseEditor::close() const {
|
||||
this->closed.emit(itemName());
|
||||
}
|
||||
@ -100,6 +107,11 @@ ox::StringView BaseEditor::pathToItemName(ox::CRStringView path) noexcept {
|
||||
return path.substr(lastSlash + 1);
|
||||
}
|
||||
|
||||
void BaseEditor::setRequiresConstantRefresh(bool value) noexcept {
|
||||
m_requiresConstantRefresh = value;
|
||||
}
|
||||
|
||||
|
||||
Editor::Editor() noexcept {
|
||||
m_undoStack.changeTriggered.connect(this, &Editor::markUnsavedChanges);
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ class NOSTALGIASTUDIO_EXPORT BaseEditor: public Widget {
|
||||
bool m_cutEnabled = false;
|
||||
bool m_copyEnabled = false;
|
||||
bool m_pasteEnabled = false;
|
||||
bool m_requiresConstantRefresh = false;
|
||||
|
||||
public:
|
||||
~BaseEditor() override = default;
|
||||
@ -50,6 +51,11 @@ class NOSTALGIASTUDIO_EXPORT BaseEditor: public Widget {
|
||||
|
||||
virtual void keyStateChanged(core::Key key, bool down);
|
||||
|
||||
virtual void onActivated() noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
bool requiresConstantRefresh() const noexcept;
|
||||
|
||||
void close() const;
|
||||
|
||||
/**
|
||||
@ -102,6 +108,8 @@ class NOSTALGIASTUDIO_EXPORT BaseEditor: public Widget {
|
||||
|
||||
static ox::StringView pathToItemName(ox::CRStringView path) noexcept;
|
||||
|
||||
void setRequiresConstantRefresh(bool value) noexcept;
|
||||
|
||||
// signals
|
||||
public:
|
||||
ox::Signal<ox::Error(bool)> unsavedChangesChanged;
|
||||
|
@ -14,7 +14,7 @@
|
||||
namespace nostalgia::studio {
|
||||
|
||||
static void generateTypes(ox::TypeStore *ts) noexcept {
|
||||
for (const auto mod : *foundation::modules()) {
|
||||
for (const auto mod : foundation::modules()) {
|
||||
for (auto gen : mod->types()) {
|
||||
oxLogError(gen(ts));
|
||||
}
|
||||
|
@ -48,13 +48,16 @@ static ox::Error run(ox::UniquePtr<ox::FileSystem> fs) noexcept {
|
||||
core::setUpdateHandler(ctx.get(), updateHandler);
|
||||
core::setKeyEventHandler(ctx.get(), keyEventHandler);
|
||||
core::setConstantRefresh(ctx.get(), false);
|
||||
core::gl::setMainViewEnabled(false);
|
||||
studio::StudioContext studioCtx;
|
||||
core::setApplicationData(ctx.get(), &studioCtx);
|
||||
StudioUI ui(ctx.get());
|
||||
studioCtx.ui = &ui;
|
||||
StudioUIDrawer drawer(&ui);
|
||||
ctx->drawers.emplace_back(&drawer);
|
||||
return core::run(ctx.get());
|
||||
core::addCustomDrawer(ctx.get(), &drawer);
|
||||
auto err = core::run(ctx.get());
|
||||
core::removeCustomDrawer(ctx.get(), &drawer);
|
||||
return err;
|
||||
}
|
||||
|
||||
static ox::Error run(int, const char**) noexcept {
|
||||
|
@ -217,7 +217,12 @@ void StudioUI::drawTabs() noexcept {
|
||||
if (m_activeEditorUpdatePending == e.get()) {
|
||||
m_activeEditorUpdatePending = nullptr;
|
||||
}
|
||||
if (m_activeEditorOnLastDraw != e.get()) [[unlikely]] {
|
||||
m_activeEditor->onActivated();
|
||||
core::setConstantRefresh(m_ctx, m_activeEditor->requiresConstantRefresh());
|
||||
}
|
||||
e->draw(m_ctx);
|
||||
m_activeEditorOnLastDraw = e.get();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (!open) {
|
||||
@ -346,7 +351,7 @@ ox::Error StudioUI::openFileActiveTab(ox::CRStringView path, bool makeActiveTab)
|
||||
}
|
||||
// save to config
|
||||
studio::editConfig<StudioConfig>(m_ctx, [&](StudioConfig *config) {
|
||||
if (!config->openFiles.contains((path))) {
|
||||
if (!config->openFiles.contains(path)) {
|
||||
config->openFiles.emplace_back(path);
|
||||
}
|
||||
});
|
||||
|
@ -31,6 +31,7 @@ class StudioUI: public ox::SignalHandler {
|
||||
ox::HashMap<ox::String, studio::EditorMaker::Func> m_editorMakers;
|
||||
ox::UniquePtr<ProjectExplorer> m_projectExplorer;
|
||||
ox::Vector<ox::String> m_openFiles;
|
||||
studio::BaseEditor *m_activeEditorOnLastDraw = nullptr;
|
||||
studio::BaseEditor *m_activeEditor = nullptr;
|
||||
studio::BaseEditor *m_activeEditorUpdatePending = nullptr;
|
||||
NewMenu m_newMenu;
|
||||
|
Loading…
x
Reference in New Issue
Block a user