diff --git a/src/nostalgia/appmodules/appmodules.cpp b/src/nostalgia/appmodules/appmodules.cpp index 63fa8165..b5efeabd 100644 --- a/src/nostalgia/appmodules/appmodules.cpp +++ b/src/nostalgia/appmodules/appmodules.cpp @@ -2,8 +2,6 @@ * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved. */ -#include - #include #include @@ -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; } diff --git a/src/nostalgia/core/CMakeLists.txt b/src/nostalgia/core/CMakeLists.txt index 3bbbdd4e..24f685c3 100644 --- a/src/nostalgia/core/CMakeLists.txt +++ b/src/nostalgia/core/CMakeLists.txt @@ -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 diff --git a/src/nostalgia/core/consts.hpp b/src/nostalgia/core/consts.hpp index 5143c80f..4faa07b7 100644 --- a/src/nostalgia/core/consts.hpp +++ b/src/nostalgia/core/consts.hpp @@ -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"; } diff --git a/src/nostalgia/core/context.hpp b/src/nostalgia/core/context.hpp index da8be4d9..acd32253 100644 --- a/src/nostalgia/core/context.hpp +++ b/src/nostalgia/core/context.hpp @@ -9,10 +9,22 @@ #include #include +#include #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, @@ -84,14 +97,18 @@ class Context: public foundation::Context { friend constexpr KeyEventHandler keyEventHandler(Context *ctx) noexcept; friend void setTile(Context *ctx, unsigned bgIdx, int column, int row, uint8_t tile) noexcept; friend void setSprite(Context *ctx, - unsigned idx, - int x, - int y, - unsigned tileIdx, - unsigned spriteShape, - unsigned spriteSize, - unsigned flipX) noexcept; + unsigned idx, + int x, + int y, + unsigned tileIdx, + unsigned spriteShape, + 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 drawers; diff --git a/src/nostalgia/core/gfx.hpp b/src/nostalgia/core/gfx.hpp index 57423a4d..9de4bf2e 100644 --- a/src/nostalgia/core/gfx.hpp +++ b/src/nostalgia/core/gfx.hpp @@ -18,6 +18,12 @@ namespace nostalgia::core { +namespace gl { + +void setMainViewEnabled(bool) noexcept; + +} + extern ox::Array charMap; class Drawer { diff --git a/src/nostalgia/core/glfw/gfx.cpp b/src/nostalgia/core/glfw/gfx.cpp index a8628674..eccdb1b8 100644 --- a/src/nostalgia/core/glfw/gfx.cpp +++ b/src/nostalgia/core/glfw/gfx.cpp @@ -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); } diff --git a/src/nostalgia/core/headless/core.cpp b/src/nostalgia/core/headless/core.cpp deleted file mode 100644 index 00791393..00000000 --- a/src/nostalgia/core/headless/core.cpp +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved. - */ - -#include -#include - -namespace nostalgia::core { - -ox::Result> init(ox::UniquePtr, 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; -} - -} diff --git a/src/nostalgia/core/headless/gfx.cpp b/src/nostalgia/core/headless/gfx.cpp deleted file mode 100644 index f55ef7a0..00000000 --- a/src/nostalgia/core/headless/gfx.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved. - */ - -#include -#include - -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 { -} - -} diff --git a/src/nostalgia/core/module.cpp b/src/nostalgia/core/module.cpp index f330b11b..8b3e1a9b 100644 --- a/src/nostalgia/core/module.cpp +++ b/src/nostalgia/core/module.cpp @@ -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 types() const noexcept override; + [[nodiscard]] + ox::Vector converters() const noexcept override; + [[nodiscard]] + ox::Vector packTransforms() const noexcept override; +}; + CoreModule CoreModule::mod; +const foundation::Module *module() noexcept { + return &CoreModule::mod; +} + ox::Vector CoreModule::types() const noexcept { return { foundation::generateTypeDesc, diff --git a/src/nostalgia/core/module.hpp b/src/nostalgia/core/module.hpp index 2258da12..bd741bc3 100644 --- a/src/nostalgia/core/module.hpp +++ b/src/nostalgia/core/module.hpp @@ -6,25 +6,8 @@ #include -#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 types() const noexcept override; - [[nodiscard]] - ox::Vector converters() const noexcept override; - [[nodiscard]] - ox::Vector packTransforms() const noexcept override; -}; +const foundation::Module *module() noexcept; } diff --git a/src/nostalgia/core/opengl/gfx_opengl.cpp b/src/nostalgia/core/opengl/gfx_opengl.cpp index 1e6cd9d1..df8c7ada 100644 --- a/src/nostalgia/core/opengl/gfx_opengl.cpp +++ b/src/nostalgia/core/opengl/gfx_opengl.cpp @@ -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 spriteStates; ox::Array backgrounds; + ox::Optional 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(sh) / static_cast(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(sh) / static_cast(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(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(glGetUniformLocation(id->bgShader, "vXScale")); const auto uniformTileHeight = static_cast(glGetUniformLocation(id->bgShader, "vTileHeight")); - //glUniform3fv(uniformPalette, GlImplData::ColorCnt, id->palette.data()); + const auto [wi, hi] = gl::getRenderSize(ctx); + const auto wf = static_cast(wi); + const auto hf = static_cast(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(glGetUniformLocation(id->bgShader, "vXScale")); const auto uniformTileHeight = static_cast(glGetUniformLocation(id->spriteShader, "vTileHeight")); + const auto [wi, hi] = gl::getRenderSize(ctx); + const auto wf = static_cast(wi); + const auto hf = static_cast(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(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(); - *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::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(); + id->renderSize.emplace(width, height); +} + +void clearRenderSize(core::Context *ctx) noexcept { + auto id = ctx->rendererData(); + id->renderSize.reset(); +} + +geo::Size getRenderSize(core::Context *ctx) noexcept { + const auto id = ctx->rendererData(); + if (id->renderSize.has_value()) { + return id->renderSize.value(); + } else { + return core::getScreenSize(ctx); + } +} + +} + } diff --git a/src/nostalgia/foundation/asset.cpp b/src/nostalgia/foundation/asset.cpp index 6d15d049..1d743891 100644 --- a/src/nostalgia/foundation/asset.cpp +++ b/src/nostalgia/foundation/asset.cpp @@ -11,19 +11,20 @@ ox::Result readUuidHeader(const ox::Buffer &buff) noexcept { } ox::Result 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 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 readAsset(ox::TypeStore *ts, const ox::Buffer &buff) ox::Result 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)); diff --git a/src/nostalgia/foundation/asset.hpp b/src/nostalgia/foundation/asset.hpp index e5a7306d..df1be686 100644 --- a/src/nostalgia/foundation/asset.hpp +++ b/src/nostalgia/foundation/asset.hpp @@ -9,17 +9,16 @@ #include #include -#include - namespace nostalgia::foundation { -[[nodiscard]] +constexpr auto N1HdrSz = 40; + ox::Result readUuidHeader(const ox::Buffer &buff) noexcept; ox::Result 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>("N1;{};", uuid.toString()); + const auto hdr = ox::sfmt>("N1;{};", uuid.toString()); return write(writer, hdr); } @@ -28,7 +27,7 @@ ox::Result 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(buff.data() + offset, buff.size() - offset); } diff --git a/src/nostalgia/foundation/assetmanager.hpp b/src/nostalgia/foundation/assetmanager.hpp index d249915c..c27979a8 100644 --- a/src/nostalgia/foundation/assetmanager.hpp +++ b/src/nostalgia/foundation/assetmanager.hpp @@ -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(); diff --git a/src/nostalgia/foundation/foundation.hpp b/src/nostalgia/foundation/foundation.hpp index bf6cdccf..ce0ebde9 100644 --- a/src/nostalgia/foundation/foundation.hpp +++ b/src/nostalgia/foundation/foundation.hpp @@ -17,17 +17,15 @@ ox::Result> init(ox::UPtr &&fs, ox::CRStringView a auto ctx = ox::make_unique(); ctx->appName = appName; oxIgnoreError(setRomFs(ctx.get(), std::move(fs))); - auto mods = modules(); - if (mods) { - for (auto &mod : *mods) { - // register type converters - for (auto c : mod->converters()) { - ctx->converters.emplace_back(c); - } - // register pack transforms - for (auto c : mod->packTransforms()) { - ctx->packTransforms.emplace_back(c); - } + const auto &mods = modules(); + for (auto &mod : mods) { + // register type converters + for (auto c : mod->converters()) { + ctx->converters.emplace_back(c); + } + // register pack transforms + for (auto c : mod->packTransforms()) { + ctx->packTransforms.emplace_back(c); } } return ctx; diff --git a/src/nostalgia/foundation/module.cpp b/src/nostalgia/foundation/module.cpp index f1e75845..51157ee5 100644 --- a/src/nostalgia/foundation/module.cpp +++ b/src/nostalgia/foundation/module.cpp @@ -13,8 +13,8 @@ void registerModule(const Module *mod) noexcept { } [[nodiscard]] -const ox::Vector *modules() noexcept { - return &mods; +const ox::Vector &modules() noexcept { + return mods; } diff --git a/src/nostalgia/foundation/module.hpp b/src/nostalgia/foundation/module.hpp index 04acff1b..ff8f559a 100644 --- a/src/nostalgia/foundation/module.hpp +++ b/src/nostalgia/foundation/module.hpp @@ -38,6 +38,6 @@ class Module { void registerModule(const Module *mod) noexcept; [[nodiscard]] -const ox::Vector *modules() noexcept; +const ox::Vector &modules() noexcept; } diff --git a/src/nostalgia/foundation/typeconv.hpp b/src/nostalgia/foundation/typeconv.hpp index 045b4a40..2ed38139 100644 --- a/src/nostalgia/foundation/typeconv.hpp +++ b/src/nostalgia/foundation/typeconv.hpp @@ -176,7 +176,7 @@ ox::Result convertBuffToBuff(foundation::Context *ctx, const ox::Buf } template -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); diff --git a/src/nostalgia/player/app.cpp b/src/nostalgia/player/app.cpp index 2655ab77..fa6a885f 100644 --- a/src/nostalgia/player/app.cpp +++ b/src/nostalgia/player/app.cpp @@ -3,7 +3,6 @@ */ #include -#include #include using namespace nostalgia; @@ -37,7 +36,7 @@ ox::Error run(ox::UniquePtr fs) noexcept { oxRequire(scn, foundation::readObj(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()); } diff --git a/src/nostalgia/player/main.cpp b/src/nostalgia/player/main.cpp index 4f42c3ca..2b47ed20 100644 --- a/src/nostalgia/player/main.cpp +++ b/src/nostalgia/player/main.cpp @@ -5,7 +5,6 @@ #include #include -#include #include diff --git a/src/nostalgia/scene/CMakeLists.txt b/src/nostalgia/scene/CMakeLists.txt index 610736da..60804820 100644 --- a/src/nostalgia/scene/CMakeLists.txt +++ b/src/nostalgia/scene/CMakeLists.txt @@ -22,6 +22,6 @@ install( include/nostalgia/scene ) -#if(NOSTALGIA_BUILD_STUDIO) -# add_subdirectory(studio) -#endif() +if(NOSTALGIA_BUILD_STUDIO) + add_subdirectory(studio) +endif() diff --git a/src/nostalgia/scene/scene.cpp b/src/nostalgia/scene/scene.cpp index e80564e5..14586039 100644 --- a/src/nostalgia/scene/scene.cpp +++ b/src/nostalgia/scene/scene.cpp @@ -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); diff --git a/src/nostalgia/scene/scene.hpp b/src/nostalgia/scene/scene.hpp index 6189103f..e60732f7 100644 --- a/src/nostalgia/scene/scene.hpp +++ b/src/nostalgia/scene/scene.hpp @@ -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; diff --git a/src/nostalgia/scene/scenemodule.cpp b/src/nostalgia/scene/scenemodule.cpp index 93a7d69b..62c41522 100644 --- a/src/nostalgia/scene/scenemodule.cpp +++ b/src/nostalgia/scene/scenemodule.cpp @@ -5,29 +5,44 @@ #include #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 SceneModule::types() const noexcept { - return { - foundation::generateTypeDesc, - foundation::generateTypeDesc, - }; -} + public: + [[nodiscard]] + ox::Vector types() const noexcept override { + return { + foundation::generateTypeDesc, + foundation::generateTypeDesc, + }; + } -ox::Vector SceneModule::converters() const noexcept { - return { - &sceneDocToSceneStaticConverter, - }; -} + [[nodiscard]] + ox::Vector converters() const noexcept override { + return { + &sceneDocToSceneStaticConverter, + }; + } -ox::Vector SceneModule::packTransforms() const noexcept { - return { - foundation::transformRule, - }; + [[nodiscard]] + ox::Vector packTransforms() const noexcept override { + return { + foundation::transformRule, + }; + } + +}; + +static SceneModule mod; +const foundation::Module *module() noexcept { + return &mod; } } diff --git a/src/nostalgia/scene/scenemodule.hpp b/src/nostalgia/scene/scenemodule.hpp index 867eb85d..109b087b 100644 --- a/src/nostalgia/scene/scenemodule.hpp +++ b/src/nostalgia/scene/scenemodule.hpp @@ -6,22 +6,8 @@ #include -#include "typeconv.hpp" - namespace nostalgia::scene { -class SceneModule: public foundation::Module { - private: - SceneDocToSceneStaticConverter sceneDocToSceneStaticConverter; - - public: - static SceneModule mod; - [[nodiscard]] - ox::Vector types() const noexcept override; - [[nodiscard]] - ox::Vector converters() const noexcept override; - [[nodiscard]] - ox::Vector packTransforms() const noexcept override; -}; +const foundation::Module *module() noexcept; } diff --git a/src/nostalgia/scene/scenestatic.hpp b/src/nostalgia/scene/scenestatic.hpp index 794d3f3c..a66fccfd 100644 --- a/src/nostalgia/scene/scenestatic.hpp +++ b/src/nostalgia/scene/scenestatic.hpp @@ -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 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 layerAttachments; [[nodiscard]] constexpr ox::Result 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 &tileMapIdx; ox::Vector &tileType; + ox::Vector &layerAttachments; constexpr Layer( - uint16_t *pColumns, - uint16_t *pRows, - ox::Vector *pTileMapIdx, - ox::Vector *pTileType) noexcept: - columns(*pColumns), - rows(*pRows), - tileMapIdx(*pTileMapIdx), - tileType(*pTileType) { + uint16_t &pColumns, + uint16_t &pRows, + ox::Vector &pTileMapIdx, + ox::Vector &pTileType, + ox::Vector &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(columns * rows); tileMapIdx.resize(tileCnt); tileType.resize(tileCnt); + layerAttachments.resize(tileCnt); } }; @@ -137,13 +187,21 @@ struct SceneStatic { ox::Vector rows; ox::Vector> tileMapIdx; ox::Vector> tileType; + ox::Vector> 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() } diff --git a/src/nostalgia/scene/typeconv.cpp b/src/nostalgia/scene/typeconv.cpp index 517736f8..15a059cd 100644 --- a/src/nostalgia/scene/typeconv.cpp +++ b/src/nostalgia/scene/typeconv.cpp @@ -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(mapIdx); + setLayerAttachments(layerIdx, srcTile, dstTile); ++tileIdx; } } diff --git a/src/nostalgia/studio/CMakeLists.txt b/src/nostalgia/studio/CMakeLists.txt index 5e7cd647..e54ff6c8 100644 --- a/src/nostalgia/studio/CMakeLists.txt +++ b/src/nostalgia/studio/CMakeLists.txt @@ -19,6 +19,7 @@ target_link_libraries( NostalgiaAppModules NostalgiaStudio NostalgiaCore-Studio + NostalgiaScene-Studio ) if(CMAKE_BUILD_TYPE STREQUAL "Release" AND NOT WIN32) diff --git a/src/nostalgia/studio/builtinmodules.hpp b/src/nostalgia/studio/builtinmodules.hpp index 533dacaf..af276365 100644 --- a/src/nostalgia/studio/builtinmodules.hpp +++ b/src/nostalgia/studio/builtinmodules.hpp @@ -7,13 +7,17 @@ #include #include +#include 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(); +[[maybe_unused]] // GCC warns about the existence of this "unused" inline list in a header file... +inline ox::Vector()>, 2> BuiltinModules = { + []() -> ox::UPtr { + return ox::UPtr(new core::StudioModule()); + }, + []() -> ox::UPtr { + return ox::UPtr(new scene::StudioModule()); }, }; diff --git a/src/nostalgia/studio/lib/configio.cpp b/src/nostalgia/studio/lib/configio.cpp index a64b70dd..1fa71f10 100644 --- a/src/nostalgia/studio/lib/configio.cpp +++ b/src/nostalgia/studio/lib/configio.cpp @@ -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); } diff --git a/src/nostalgia/studio/lib/configio.hpp b/src/nostalgia/studio/lib/configio.hpp index 0391d6b0..172643e4 100644 --- a/src/nostalgia/studio/lib/configio.hpp +++ b/src/nostalgia/studio/lib/configio.hpp @@ -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 -ox::Result readConfig(core::Context *ctx, ox::CRStringView name) noexcept { +ox::Result 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 readConfig(core::Context *ctx, ox::CRStringView name) noexcept { } template -ox::Result readConfig(core::Context *ctx) noexcept { +ox::Result readConfig(foundation::Context *ctx) noexcept { constexpr auto TypeName = ox::requireModelTypeName(); return readConfig(ctx, TypeName); } template -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 -ox::Error writeConfig(core::Context *ctx, T *data) noexcept { +ox::Error writeConfig(foundation::Context *ctx, T *data) noexcept { constexpr auto TypeName = ox::requireModelTypeName(); return writeConfig(ctx, TypeName, data); } template -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(ctx, name); oxLogError(err); @@ -72,13 +72,13 @@ void openConfig(core::Context *ctx, const auto &name, Func f) noexcept { } template -void openConfig(core::Context *ctx, Func f) noexcept { +void openConfig(foundation::Context *ctx, Func f) noexcept { constexpr auto TypeName = ox::requireModelTypeName(); openConfig(ctx, TypeName, f); } template -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(ctx, name); oxLogError(err); @@ -87,7 +87,7 @@ void editConfig(core::Context *ctx, const auto &name, Func f) noexcept { } template -void editConfig(core::Context *ctx, Func f) noexcept { +void editConfig(foundation::Context *ctx, Func f) noexcept { constexpr auto TypeName = ox::requireModelTypeName(); editConfig(ctx, TypeName, f); } diff --git a/src/nostalgia/studio/lib/editor.cpp b/src/nostalgia/studio/lib/editor.cpp index b9160005..353868d1 100644 --- a/src/nostalgia/studio/lib/editor.cpp +++ b/src/nostalgia/studio/lib/editor.cpp @@ -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); } diff --git a/src/nostalgia/studio/lib/editor.hpp b/src/nostalgia/studio/lib/editor.hpp index 5d350d68..5fc6e5a4 100644 --- a/src/nostalgia/studio/lib/editor.hpp +++ b/src/nostalgia/studio/lib/editor.hpp @@ -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 unsavedChangesChanged; diff --git a/src/nostalgia/studio/lib/project.cpp b/src/nostalgia/studio/lib/project.cpp index 3feee187..cc67714a 100644 --- a/src/nostalgia/studio/lib/project.cpp +++ b/src/nostalgia/studio/lib/project.cpp @@ -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)); } diff --git a/src/nostalgia/studio/main.cpp b/src/nostalgia/studio/main.cpp index b40aeecf..e0f56b19 100644 --- a/src/nostalgia/studio/main.cpp +++ b/src/nostalgia/studio/main.cpp @@ -48,13 +48,16 @@ static ox::Error run(ox::UniquePtr 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 { diff --git a/src/nostalgia/studio/studioapp.cpp b/src/nostalgia/studio/studioapp.cpp index 8d73b4c1..476abaf4 100644 --- a/src/nostalgia/studio/studioapp.cpp +++ b/src/nostalgia/studio/studioapp.cpp @@ -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(m_ctx, [&](StudioConfig *config) { - if (!config->openFiles.contains((path))) { + if (!config->openFiles.contains(path)) { config->openFiles.emplace_back(path); } }); diff --git a/src/nostalgia/studio/studioapp.hpp b/src/nostalgia/studio/studioapp.hpp index 9bc45922..82fcc8c0 100644 --- a/src/nostalgia/studio/studioapp.hpp +++ b/src/nostalgia/studio/studioapp.hpp @@ -31,6 +31,7 @@ class StudioUI: public ox::SignalHandler { ox::HashMap m_editorMakers; ox::UniquePtr m_projectExplorer; ox::Vector m_openFiles; + studio::BaseEditor *m_activeEditorOnLastDraw = nullptr; studio::BaseEditor *m_activeEditor = nullptr; studio::BaseEditor *m_activeEditorUpdatePending = nullptr; NewMenu m_newMenu;