From facde6bdce5479ffea04571d5114005fad4cb0bb Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Fri, 8 Dec 2023 23:59:02 -0600 Subject: [PATCH] [keel,nostalgia,studio,turbine] Cleanup structure of Turbine --- src/keel/pack.hpp | 2 +- src/keel/typeconv.cpp | 22 ++-- .../core/include/nostalgia/core/context.hpp | 2 +- .../modules/core/src/gba/CMakeLists.txt | 3 +- .../modules/core/src/gba/context.hpp | 4 +- src/nostalgia/modules/core/src/gba/gfx.cpp | 8 +- src/nostalgia/modules/core/src/gfx.cpp | 6 +- src/nostalgia/modules/core/src/opengl/gfx.cpp | 4 +- src/nostalgia/modules/core/src/opengl/gfx.hpp | 2 +- .../core/src/studio/paletteeditor-imgui.cpp | 4 +- .../core/src/studio/tilesheeteditormodel.cpp | 10 +- .../scene/include/nostalgia/scene/scene.hpp | 2 +- .../include/nostalgia/scene/scenestatic.hpp | 6 +- src/nostalgia/modules/scene/src/scene.cpp | 6 +- .../scene/src/studio/sceneeditor-imgui.cpp | 2 +- .../modules/scene/src/studio/sceneeditor.cpp | 2 +- .../modules/scene/src/studio/studiomodule.cpp | 2 +- src/nostalgia/player/app.cpp | 2 +- src/studio/applib/src/aboutpopup.cpp | 2 +- src/studio/applib/src/main.cpp | 2 +- src/studio/applib/src/projectexplorer.hpp | 2 +- src/studio/applib/src/studioapp.cpp | 18 +-- .../modlib/include/studio/itemmaker.hpp | 4 +- src/turbine/CMakeLists.txt | 36 +---- src/turbine/clipboard.hpp | 32 ----- src/turbine/config.hpp | 25 ---- src/turbine/context.hpp | 102 --------------- src/turbine/gba/context.hpp | 29 ----- src/turbine/glfw/CMakeLists.txt | 12 -- src/turbine/glfw/clipboard.cpp | 27 ---- src/turbine/glfw/context.hpp | 25 ---- src/turbine/glfw/turbine.cpp | 122 ----------------- src/turbine/include/turbine/clipboard.hpp | 50 +++++++ src/turbine/include/turbine/context.hpp | 56 ++++++++ src/turbine/{ => include/turbine}/event.hpp | 0 src/turbine/{ => include/turbine}/gfx.hpp | 4 +- src/turbine/{ => include/turbine}/input.hpp | 2 +- src/turbine/{ => include/turbine}/turbine.hpp | 7 +- src/turbine/src/CMakeLists.txt | 40 ++++++ src/turbine/{ => src}/gba/CMakeLists.txt | 16 +++ src/turbine/{ => src}/gba/clipboard.cpp | 1 - src/turbine/src/gba/config.hpp | 12 ++ src/turbine/src/gba/context.cpp | 29 +++++ src/turbine/src/gba/context.hpp | 36 +++++ src/turbine/{ => src/gba}/event.cpp | 13 +- src/turbine/{ => src}/gba/gfx.cpp | 2 +- src/turbine/{ => src}/gba/irq.arm.cpp | 0 src/turbine/{ => src}/gba/irq.s | 0 src/turbine/{ => src}/gba/irqstub.cpp | 0 src/turbine/{ => src}/gba/turbine.arm.cpp | 3 +- src/turbine/{ => src}/gba/turbine.cpp | 17 +-- src/turbine/{ => src}/gba/turbine.hpp | 2 +- src/turbine/src/glfw/CMakeLists.txt | 24 ++++ src/turbine/src/glfw/clipboard.cpp | 36 +++++ src/turbine/src/glfw/config.hpp | 11 ++ src/turbine/src/glfw/context.cpp | 31 +++++ src/turbine/src/glfw/context.hpp | 41 ++++++ src/turbine/src/glfw/event.cpp | 23 ++++ src/turbine/{ => src}/glfw/gfx.cpp | 120 +++++++---------- src/turbine/src/glfw/turbine.cpp | 123 ++++++++++++++++++ 60 files changed, 669 insertions(+), 557 deletions(-) delete mode 100644 src/turbine/clipboard.hpp delete mode 100644 src/turbine/config.hpp delete mode 100644 src/turbine/context.hpp delete mode 100644 src/turbine/gba/context.hpp delete mode 100644 src/turbine/glfw/CMakeLists.txt delete mode 100644 src/turbine/glfw/clipboard.cpp delete mode 100644 src/turbine/glfw/context.hpp delete mode 100644 src/turbine/glfw/turbine.cpp create mode 100644 src/turbine/include/turbine/clipboard.hpp create mode 100644 src/turbine/include/turbine/context.hpp rename src/turbine/{ => include/turbine}/event.hpp (100%) rename src/turbine/{ => include/turbine}/gfx.hpp (87%) rename src/turbine/{ => include/turbine}/input.hpp (94%) rename src/turbine/{ => include/turbine}/turbine.hpp (68%) create mode 100644 src/turbine/src/CMakeLists.txt rename src/turbine/{ => src}/gba/CMakeLists.txt (53%) rename src/turbine/{ => src}/gba/clipboard.cpp (99%) create mode 100644 src/turbine/src/gba/config.hpp create mode 100644 src/turbine/src/gba/context.cpp create mode 100644 src/turbine/src/gba/context.hpp rename src/turbine/{ => src/gba}/event.cpp (50%) rename src/turbine/{ => src}/gba/gfx.cpp (94%) rename src/turbine/{ => src}/gba/irq.arm.cpp (100%) rename src/turbine/{ => src}/gba/irq.s (100%) rename src/turbine/{ => src}/gba/irqstub.cpp (100%) rename src/turbine/{ => src}/gba/turbine.arm.cpp (91%) rename src/turbine/{ => src}/gba/turbine.cpp (80%) rename src/turbine/{ => src}/gba/turbine.hpp (89%) create mode 100644 src/turbine/src/glfw/CMakeLists.txt create mode 100644 src/turbine/src/glfw/clipboard.cpp create mode 100644 src/turbine/src/glfw/config.hpp create mode 100644 src/turbine/src/glfw/context.cpp create mode 100644 src/turbine/src/glfw/context.hpp create mode 100644 src/turbine/src/glfw/event.cpp rename src/turbine/{ => src}/glfw/gfx.cpp (78%) create mode 100644 src/turbine/src/glfw/turbine.cpp diff --git a/src/keel/pack.hpp b/src/keel/pack.hpp index 888f621c..66209ba4 100644 --- a/src/keel/pack.hpp +++ b/src/keel/pack.hpp @@ -134,7 +134,7 @@ ox::Error preloadDir( } template -ox::Error appendBinary(ox::Buffer &binBuff, ox::Buffer &fsBuff, ox::Preloader &pl) noexcept { +ox::Error appendBinary(ox::Buffer &binBuff, ox::SpanView const&fsBuff, ox::Preloader &pl) noexcept { constexpr auto padbin = [](ox::BufferWriter &w, unsigned factor) noexcept -> ox::Error { return w.write(nullptr, factor - w.buff().size() % factor); }; diff --git a/src/keel/typeconv.cpp b/src/keel/typeconv.cpp index b3e4483e..0ce33c40 100644 --- a/src/keel/typeconv.cpp +++ b/src/keel/typeconv.cpp @@ -9,15 +9,14 @@ namespace keel { -#ifndef OX_BARE_METAL [[nodiscard]] static ox::Result findConverter( - keel::Context &ctx, + ox::Vector const&converters, ox::CRStringView srcTypeName, int srcTypeVersion, ox::CRStringView dstTypeName, int dstTypeVersion) noexcept { - for (auto &c : ctx.converters) { + for (auto &c : converters) { if (c->matches(srcTypeName, srcTypeVersion, dstTypeName, dstTypeVersion)) { return c; } @@ -27,23 +26,24 @@ static ox::Result findConverter( static ox::Result> convert( [[maybe_unused]] keel::Context &ctx, + ox::Vector const&converters, [[maybe_unused]] const ox::Buffer &srcBuffer, [[maybe_unused]] ox::CRStringView srcTypeName, [[maybe_unused]] int srcTypeVersion, [[maybe_unused]] ox::CRStringView dstTypeName, [[maybe_unused]] int dstTypeVersion) noexcept { // look for direct converter - auto [c, err] = findConverter(ctx, srcTypeName, srcTypeVersion, dstTypeName, dstTypeVersion); + auto [c, err] = findConverter(converters, srcTypeName, srcTypeVersion, dstTypeName, dstTypeVersion); if (!err) { return c->convertBuffToPtr(ctx, srcBuffer); } // try to chain multiple converters - for (const auto &subConverter : ctx.converters) { + for (const auto &subConverter : converters) { if (!subConverter->dstMatches(dstTypeName, dstTypeVersion)) { continue; } const auto [intermediate, chainErr] = - convert(ctx, srcBuffer, srcTypeName, srcTypeVersion, + convert(ctx, converters, srcBuffer, srcTypeName, srcTypeVersion, subConverter->srcTypeName(), subConverter->srcTypeVersion()); if (!chainErr) { return subConverter->convertPtrToPtr(ctx, *intermediate); @@ -51,7 +51,6 @@ static ox::Result> convert( } return OxError(1, "Could not convert between types"); } -#endif ox::Result> convert( [[maybe_unused]] keel::Context &ctx, @@ -60,7 +59,14 @@ ox::Result> convert( [[maybe_unused]] int dstTypeVersion) noexcept { #ifndef OX_BARE_METAL oxRequire(hdr, readAssetHeader(srcBuffer)); - return convert(ctx, srcBuffer, hdr.clawHdr.typeName, hdr.clawHdr.typeVersion, dstTypeName, dstTypeVersion); + return convert( + ctx, + ctx.converters, + srcBuffer, + hdr.clawHdr.typeName, + hdr.clawHdr.typeVersion, + dstTypeName, + dstTypeVersion); #else return OxError(1, "Operation not supported on this platform"); #endif diff --git a/src/nostalgia/modules/core/include/nostalgia/core/context.hpp b/src/nostalgia/modules/core/include/nostalgia/core/context.hpp index ae001348..8efa2756 100644 --- a/src/nostalgia/modules/core/include/nostalgia/core/context.hpp +++ b/src/nostalgia/modules/core/include/nostalgia/core/context.hpp @@ -27,7 +27,7 @@ class Context { }; -ox::Result> init(turbine::Context &tctx, InitParams const& = {}) noexcept; +ox::Result> init(turbine::Context &tctx, InitParams const¶ms = {}) noexcept; } diff --git a/src/nostalgia/modules/core/src/gba/CMakeLists.txt b/src/nostalgia/modules/core/src/gba/CMakeLists.txt index 32c22d3c..9aa64dbd 100644 --- a/src/nostalgia/modules/core/src/gba/CMakeLists.txt +++ b/src/nostalgia/modules/core/src/gba/CMakeLists.txt @@ -12,9 +12,10 @@ target_link_libraries( NostalgiaCore-GBA PUBLIC TeaGBA Keel + Turbine ) if(TURBINE_BUILD_TYPE STREQUAL "GBA") set_source_files_properties(gfx.cpp PROPERTIES COMPILE_FLAGS -marm) target_link_libraries(NostalgiaCore PUBLIC NostalgiaCore-GBA) -endif() \ No newline at end of file +endif() diff --git a/src/nostalgia/modules/core/src/gba/context.hpp b/src/nostalgia/modules/core/src/gba/context.hpp index eea7efb8..5661eaf9 100644 --- a/src/nostalgia/modules/core/src/gba/context.hpp +++ b/src/nostalgia/modules/core/src/gba/context.hpp @@ -15,8 +15,8 @@ struct GbaContext: public core::Context { explicit GbaContext(turbine::Context &tctx) noexcept; [[nodiscard]] - auto const&rom() const noexcept { - return *turbine::rom(turbineCtx); + ox::MemFS const&rom() const noexcept { + return static_cast(*turbine::rom(turbineCtx)); } }; diff --git a/src/nostalgia/modules/core/src/gba/gfx.cpp b/src/nostalgia/modules/core/src/gba/gfx.cpp index 198d3374..e684eb2f 100644 --- a/src/nostalgia/modules/core/src/gba/gfx.cpp +++ b/src/nostalgia/modules/core/src/gba/gfx.cpp @@ -142,7 +142,7 @@ ox::Error loadBgTileSheet( ox::FileAddress const&tilesheetAddr, ox::FileAddress const&paletteAddr) noexcept { auto &gctx = static_cast(ctx); - auto &rom = static_cast(gctx.rom()); + auto &rom = gctx.rom(); return loadBgTileSheet(rom, cbb, tilesheetAddr, paletteAddr); } @@ -151,7 +151,7 @@ ox::Error loadSpriteTileSheet( ox::FileAddress const&tilesheetAddr, ox::FileAddress const&paletteAddr) noexcept { auto &gctx = static_cast(ctx); - auto &rom = static_cast(gctx.rom()); + auto &rom = gctx.rom(); oxRequire(tsStat, gctx.rom().stat(tilesheetAddr)); oxRequire(ts, rom.directAccess(tilesheetAddr)); GbaTileMapTarget target; @@ -169,7 +169,7 @@ ox::Error loadSpriteTileSheet( ox::Error loadBgPalette(Context &ctx, unsigned, ox::FileAddress const&paletteAddr) noexcept { auto &gctx = static_cast(ctx); - auto &rom = static_cast(gctx.rom()); + auto &rom = gctx.rom(); GbaPaletteTarget target; target.palette = MEM_BG_PALETTE; oxRequire(palStat, gctx.rom().stat(paletteAddr)); @@ -180,7 +180,7 @@ ox::Error loadBgPalette(Context &ctx, unsigned, ox::FileAddress const&paletteAdd ox::Error loadSpritePalette(Context &ctx, unsigned cbb, ox::FileAddress const&paletteAddr) noexcept { auto &gctx = static_cast(ctx); - auto &rom = static_cast(gctx.rom()); + auto &rom = gctx.rom(); GbaPaletteTarget target; target.palette = &MEM_SPRITE_PALETTE[cbb]; oxRequire(palStat, rom.stat(paletteAddr)); diff --git a/src/nostalgia/modules/core/src/gfx.cpp b/src/nostalgia/modules/core/src/gfx.cpp index fbe34977..956da1f9 100644 --- a/src/nostalgia/modules/core/src/gfx.cpp +++ b/src/nostalgia/modules/core/src/gfx.cpp @@ -43,7 +43,7 @@ ox::Array charMap = { 0, // space 38, // ! 0, // " - 0, // # + 49, // # 0, // $ 0, // % 0, // & @@ -132,9 +132,9 @@ ox::Array charMap = { 25, // y 26, // z 46, // { - 0, // | + 51, // | 48, // } - 0, // ~ + 50, // ~ }; void setSprite(Context &c, Sprite const&s) noexcept { diff --git a/src/nostalgia/modules/core/src/opengl/gfx.cpp b/src/nostalgia/modules/core/src/opengl/gfx.cpp index 36ae9a44..8395614f 100644 --- a/src/nostalgia/modules/core/src/opengl/gfx.cpp +++ b/src/nostalgia/modules/core/src/opengl/gfx.cpp @@ -435,7 +435,7 @@ ox::Error loadBgTileSheet( ox::FileAddress const&tilesheetAddr, ox::FileAddress const&paletteAddr) noexcept { auto &gctx = glctx(ctx); - auto &kctx = gctx.turbineCtx.keelCtx; + auto &kctx = keelCtx(gctx.turbineCtx); oxRequire(tilesheet, readObj(kctx, tilesheetAddr)); oxRequire(palette, readObj(kctx, paletteAddr ? paletteAddr : tilesheet->defaultPalette)); oxRequire(tsd, loadTileSheet(ctx, *tilesheet).to([](TileSheetData const&t) -> TileSheetData { @@ -455,7 +455,7 @@ ox::Error loadSpriteTileSheet( ox::FileAddress const&tilesheetAddr, ox::FileAddress const&paletteAddr) noexcept { auto &gctx = glctx(ctx); - auto &kctx = gctx.turbineCtx.keelCtx; + auto &kctx = keelCtx(gctx.turbineCtx); oxRequire(tilesheet, readObj(kctx, tilesheetAddr)); oxRequire(palette, readObj(kctx, paletteAddr ? paletteAddr : tilesheet->defaultPalette)); oxRequire(tsd, loadTileSheet(ctx, *tilesheet)); diff --git a/src/nostalgia/modules/core/src/opengl/gfx.hpp b/src/nostalgia/modules/core/src/opengl/gfx.hpp index 0d7215a0..f54a886d 100644 --- a/src/nostalgia/modules/core/src/opengl/gfx.hpp +++ b/src/nostalgia/modules/core/src/opengl/gfx.hpp @@ -19,7 +19,7 @@ constexpr uint64_t TileColumns = 128; constexpr uint64_t TileCount = TileRows * TileColumns; constexpr uint64_t SpriteCount = 128; constexpr uint64_t BgVertexVboRows = 4; -constexpr uint64_t BgVertexVboRowLength = 4; +constexpr uint64_t BgVertexVboRowLength = 5; constexpr uint64_t BgVertexVboLength = BgVertexVboRows * BgVertexVboRowLength; constexpr uint64_t BgVertexEboLength = 6; constexpr uint64_t SpriteVertexVboRows = 256; diff --git a/src/nostalgia/modules/core/src/studio/paletteeditor-imgui.cpp b/src/nostalgia/modules/core/src/studio/paletteeditor-imgui.cpp index 3e68fd9b..9c345dff 100644 --- a/src/nostalgia/modules/core/src/studio/paletteeditor-imgui.cpp +++ b/src/nostalgia/modules/core/src/studio/paletteeditor-imgui.cpp @@ -17,9 +17,9 @@ namespace nostalgia::core { PaletteEditorImGui::PaletteEditorImGui(turbine::Context &ctx, ox::CRStringView path): m_ctx(ctx), - m_itemPath(std::move(path)), + m_itemPath(path), m_itemName(m_itemPath.substr(std::find(m_itemPath.rbegin(), m_itemPath.rend(), '/').offset() + 1)), - m_pal(*keel::readObj(m_ctx.keelCtx, ox::FileAddress(m_itemPath.c_str())).unwrapThrow()) { + m_pal(*keel::readObj(keelCtx(m_ctx), ox::FileAddress(m_itemPath.c_str())).unwrapThrow()) { } ox::String const&PaletteEditorImGui::itemName() const noexcept { diff --git a/src/nostalgia/modules/core/src/studio/tilesheeteditormodel.cpp b/src/nostalgia/modules/core/src/studio/tilesheeteditormodel.cpp index fec61fbd..21762353 100644 --- a/src/nostalgia/modules/core/src/studio/tilesheeteditormodel.cpp +++ b/src/nostalgia/modules/core/src/studio/tilesheeteditormodel.cpp @@ -567,10 +567,10 @@ class PaletteChangeCommand: public TileSheetCommand { TileSheetEditorModel::TileSheetEditorModel(turbine::Context &ctx, ox::StringView path): m_ctx(ctx), m_path(path) { - oxRequireT(img, readObj(m_ctx.keelCtx, m_path)); + oxRequireT(img, readObj(keelCtx(m_ctx), m_path)); m_img = *img; if (m_img.defaultPalette) { - oxThrowError(readObj(m_ctx.keelCtx, m_img.defaultPalette).moveTo(&m_pal)); + oxThrowError(readObj(keelCtx(m_ctx), m_img.defaultPalette).moveTo(&m_pal)); } m_pal.updated.connect(this, &TileSheetEditorModel::markUpdated); m_undoStack.changeTriggered.connect(this, &TileSheetEditorModel::markUpdatedCmdId); @@ -634,7 +634,7 @@ ox::StringView TileSheetEditorModel::palPath() const noexcept { constexpr ox::StringView uuidPrefix = "uuid://"; if (ox::beginsWith(path, uuidPrefix)) { auto uuid = ox::StringView(path.data() + uuidPrefix.bytes(), path.bytes() - uuidPrefix.bytes()); - auto out = m_ctx.keelCtx.uuidToPath.at(uuid); + auto out = keelCtx(m_ctx).uuidToPath.at(uuid); if (out.error) { return {}; } @@ -645,7 +645,7 @@ ox::StringView TileSheetEditorModel::palPath() const noexcept { } ox::Error TileSheetEditorModel::setPalette(ox::String const&path) noexcept { - oxRequire(uuid, m_ctx.keelCtx.pathToUuid.at(path)); + oxRequire(uuid, keelCtx(m_ctx).pathToUuid.at(path)); pushCommand(ox::make(activeSubSheetIdx(), m_img, uuid->toString())); return {}; } @@ -753,7 +753,7 @@ ox::Error TileSheetEditorModel::markUpdatedCmdId(const studio::UndoCommand *cmd) m_updated = true; const auto cmdId = cmd->commandId(); if (static_cast(cmdId) == CommandId::PaletteChange) { - oxReturnError(readObj(m_ctx.keelCtx, ox::StringView(m_img.defaultPalette.getPath().value)).moveTo(&m_pal)); + oxReturnError(readObj(keelCtx(m_ctx), ox::StringView(m_img.defaultPalette.getPath().value)).moveTo(&m_pal)); } auto tsCmd = dynamic_cast(cmd); auto idx = m_img.validateSubSheetIdx(tsCmd->subsheetIdx()); diff --git a/src/nostalgia/modules/scene/include/nostalgia/scene/scene.hpp b/src/nostalgia/modules/scene/include/nostalgia/scene/scene.hpp index e6ce3b71..ccc29d2a 100644 --- a/src/nostalgia/modules/scene/include/nostalgia/scene/scene.hpp +++ b/src/nostalgia/modules/scene/include/nostalgia/scene/scene.hpp @@ -12,7 +12,7 @@ namespace nostalgia::scene { class Scene { private: - const SceneStatic &m_sceneStatic; + SceneStatic const&m_sceneStatic; public: explicit Scene(SceneStatic const&sceneStatic) noexcept; diff --git a/src/nostalgia/modules/scene/include/nostalgia/scene/scenestatic.hpp b/src/nostalgia/modules/scene/include/nostalgia/scene/scenestatic.hpp index be781770..94c9db5f 100644 --- a/src/nostalgia/modules/scene/include/nostalgia/scene/scenestatic.hpp +++ b/src/nostalgia/modules/scene/include/nostalgia/scene/scenestatic.hpp @@ -37,7 +37,7 @@ struct TileDoc { ox::Array layerAttachments; [[nodiscard]] - constexpr ox::Result getSubsheetId(const core::TileSheet &ts) const noexcept { + constexpr ox::Result getSubsheetId(core::TileSheet const&ts) const noexcept { // prefer the already present ID if (subsheetId > -1) { return subsheetId; @@ -47,7 +47,7 @@ struct TileDoc { [[nodiscard]] constexpr ox::Result getSubsheetPath( - const core::TileSheet &ts) const noexcept { + core::TileSheet const&ts) const noexcept { // prefer the already present path if (!subsheetPath.len()) { return ts.getNameFor(subsheetId); @@ -88,7 +88,7 @@ struct SceneDoc { 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) { + for (auto const&row : layer) { colCnt = ox::min(colCnt, row.size()); } return {static_cast(colCnt), rowCnt}; diff --git a/src/nostalgia/modules/scene/src/scene.cpp b/src/nostalgia/modules/scene/src/scene.cpp index 08e17658..c7efe557 100644 --- a/src/nostalgia/modules/scene/src/scene.cpp +++ b/src/nostalgia/modules/scene/src/scene.cpp @@ -16,12 +16,12 @@ ox::Error Scene::setupDisplay(core::Context &ctx) const noexcept { if (m_sceneStatic.palettes.empty()) { return OxError(1, "Scene has no palettes"); } - const auto &palette = m_sceneStatic.palettes[0]; + auto const&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) { + for (auto layerNo = 0u; auto const&layer : m_sceneStatic.tileMapIdx) { setupLayer(ctx, layer, layerNo); ++layerNo; } @@ -37,7 +37,7 @@ void Scene::setupLayer( auto x = 0; auto y = 0; const auto width = m_sceneStatic.rows[layerNo]; - for (const auto &tile : layer) { + for (auto const&tile : layer) { const auto tile8 = static_cast(tile); core::setTile(ctx, layerNo, x, y, tile8); core::setTile(ctx, layerNo, x + 1, y, tile8 + 1); diff --git a/src/nostalgia/modules/scene/src/studio/sceneeditor-imgui.cpp b/src/nostalgia/modules/scene/src/studio/sceneeditor-imgui.cpp index 2aa4a734..282cad1a 100644 --- a/src/nostalgia/modules/scene/src/studio/sceneeditor-imgui.cpp +++ b/src/nostalgia/modules/scene/src/studio/sceneeditor-imgui.cpp @@ -50,7 +50,7 @@ void SceneEditorImGui::onActivated() noexcept { ox::Error SceneEditorImGui::saveItem() noexcept { const auto sctx = applicationData(m_ctx); oxReturnError(sctx->project->writeObj(m_itemPath, m_editor.scene())); - oxReturnError(m_ctx.keelCtx.assetManager.setAsset(m_itemPath, m_editor.scene())); + oxReturnError(keelCtx(m_ctx).assetManager.setAsset(m_itemPath, m_editor.scene())); return {}; } diff --git a/src/nostalgia/modules/scene/src/studio/sceneeditor.cpp b/src/nostalgia/modules/scene/src/studio/sceneeditor.cpp index c82af46d..3aea5791 100644 --- a/src/nostalgia/modules/scene/src/studio/sceneeditor.cpp +++ b/src/nostalgia/modules/scene/src/studio/sceneeditor.cpp @@ -10,7 +10,7 @@ namespace nostalgia::scene { SceneEditor::SceneEditor(turbine::Context &ctx, ox::CRStringView path): m_ctx(ctx), - m_scene(*keel::readObj(m_ctx.keelCtx, path).unwrapThrow()) { + m_scene(*keel::readObj(keelCtx(m_ctx), path).unwrapThrow()) { } } diff --git a/src/nostalgia/modules/scene/src/studio/studiomodule.cpp b/src/nostalgia/modules/scene/src/studio/studiomodule.cpp index 773a1e4d..f47ad00b 100644 --- a/src/nostalgia/modules/scene/src/studio/studiomodule.cpp +++ b/src/nostalgia/modules/scene/src/studio/studiomodule.cpp @@ -24,7 +24,7 @@ class StudioModule: public studio::Module { } }; -static StudioModule mod; +static StudioModule const mod; const studio::Module *studioModule() noexcept { return &mod; } diff --git a/src/nostalgia/player/app.cpp b/src/nostalgia/player/app.cpp index ae91fa89..a8dd28c6 100644 --- a/src/nostalgia/player/app.cpp +++ b/src/nostalgia/player/app.cpp @@ -36,7 +36,7 @@ ox::Error run(ox::UniquePtr &&fs) noexcept { oxRequireM(tctx, turbine::init(std::move(fs), "Nostalgia")); oxRequireM(cctx, core::init(*tctx)); constexpr ox::FileAddress SceneAddr = ox::StringLiteral("/Scenes/Chester.nscn"); - oxRequire(scn, keel::readObj(tctx->keelCtx, SceneAddr)); + oxRequire(scn, keel::readObj(keelCtx(*tctx), SceneAddr)); turbine::setUpdateHandler(*tctx, updateHandler); turbine::setKeyEventHandler(*tctx, keyEventHandler); s_scene.emplace(*scn); diff --git a/src/studio/applib/src/aboutpopup.cpp b/src/studio/applib/src/aboutpopup.cpp index 65bb375c..2591adcd 100644 --- a/src/studio/applib/src/aboutpopup.cpp +++ b/src/studio/applib/src/aboutpopup.cpp @@ -10,7 +10,7 @@ namespace studio { AboutPopup::AboutPopup(turbine::Context &ctx) noexcept { - m_text = ox::sfmt("{} - dev build", ctx.keelCtx.appName); + m_text = ox::sfmt("{} - dev build", keelCtx(ctx).appName); } void AboutPopup::open() noexcept { diff --git a/src/studio/applib/src/main.cpp b/src/studio/applib/src/main.cpp index 64eb99d9..5709e56a 100644 --- a/src/studio/applib/src/main.cpp +++ b/src/studio/applib/src/main.cpp @@ -47,7 +47,7 @@ static ox::Error runApp( ox::CRStringView projectDataDir, ox::UniquePtr fs) noexcept { oxRequireM(ctx, turbine::init(std::move(fs), appName)); - turbine::setWindowTitle(*ctx, ctx->keelCtx.appName); + turbine::setWindowTitle(*ctx, keelCtx(*ctx).appName); turbine::setUpdateHandler(*ctx, updateHandler); turbine::setKeyEventHandler(*ctx, keyEventHandler); turbine::setConstantRefresh(*ctx, false); diff --git a/src/studio/applib/src/projectexplorer.hpp b/src/studio/applib/src/projectexplorer.hpp index a4507b50..2c252753 100644 --- a/src/studio/applib/src/projectexplorer.hpp +++ b/src/studio/applib/src/projectexplorer.hpp @@ -26,7 +26,7 @@ class ProjectExplorer: public studio::Widget { ox::Error refreshProjectTreeModel(ox::CRStringView = {}) noexcept; [[nodiscard]] - constexpr ox::FileSystem *romFs() noexcept { + inline ox::FileSystem *romFs() noexcept { return rom(*m_ctx); } diff --git a/src/studio/applib/src/studioapp.cpp b/src/studio/applib/src/studioapp.cpp index abdd8eb0..55a62441 100644 --- a/src/studio/applib/src/studioapp.cpp +++ b/src/studio/applib/src/studioapp.cpp @@ -42,7 +42,7 @@ StudioUI::StudioUI(turbine::Context *ctx, ox::StringView projectDir) noexcept: ImGui::GetIO().IniFilename = nullptr; loadModules(); // open project and files - const auto [config, err] = studio::readConfig(&ctx->keelCtx); + const auto [config, err] = studio::readConfig(&keelCtx(*ctx)); m_showProjectExplorer = config.showProjectExplorer; if (!err) { oxIgnoreError(openProject(config.projectPath)); @@ -223,7 +223,7 @@ void StudioUI::drawTabs() noexcept { if (ImGui::BeginTabItem(e->itemDisplayName().c_str(), &open, flags)) { if (m_activeEditor != e.get()) { m_activeEditor = e.get(); - studio::editConfig(&m_ctx->keelCtx, [&](StudioConfig *config) { + studio::editConfig(&keelCtx(*m_ctx), [&](StudioConfig *config) { config->activeTabItemName = m_activeEditor->itemName(); }); } @@ -276,7 +276,7 @@ void StudioUI::loadModules() noexcept { void StudioUI::toggleProjectExplorer() noexcept { m_showProjectExplorer = !m_showProjectExplorer; - studio::editConfig(&m_ctx->keelCtx, [&](StudioConfig *config) { + studio::editConfig(&keelCtx(*m_ctx), [&](StudioConfig *config) { config->showProjectExplorer = m_showProjectExplorer; }); } @@ -303,16 +303,16 @@ void StudioUI::save() noexcept { ox::Error StudioUI::openProject(ox::CRStringView path) noexcept { oxRequireM(fs, keel::loadRomFs(path)); - oxReturnError(keel::setRomFs(m_ctx->keelCtx, std::move(fs))); - turbine::setWindowTitle(*m_ctx, ox::sfmt("{} - {}", m_ctx->keelCtx.appName, path)); - m_project = ox::make_unique(m_ctx->keelCtx, ox::String(path), m_projectDir); + oxReturnError(keel::setRomFs(keelCtx(*m_ctx), std::move(fs))); + turbine::setWindowTitle(*m_ctx, ox::sfmt("{} - {}", keelCtx(*m_ctx).appName, path)); + m_project = ox::make_unique(keelCtx(*m_ctx), ox::String(path), m_projectDir); auto sctx = applicationData(*m_ctx); sctx->project = m_project.get(); m_project->fileAdded.connect(m_projectExplorer.get(), &ProjectExplorer::refreshProjectTreeModel); m_project->fileDeleted.connect(m_projectExplorer.get(), &ProjectExplorer::refreshProjectTreeModel); m_openFiles.clear(); m_editors.clear(); - studio::editConfig(&m_ctx->keelCtx, [&](StudioConfig *config) { + studio::editConfig(&keelCtx(*m_ctx), [&](StudioConfig *config) { config->projectPath = ox::String(path); config->openFiles.clear(); }); @@ -362,7 +362,7 @@ ox::Error StudioUI::openFileActiveTab(ox::CRStringView path, bool makeActiveTab) m_activeEditorUpdatePending = editor; } // save to config - studio::editConfig(&m_ctx->keelCtx, [&](StudioConfig *config) { + studio::editConfig(&keelCtx(*m_ctx), [&](StudioConfig *config) { if (!config->openFiles.contains(path)) { config->openFiles.emplace_back(path); } @@ -376,7 +376,7 @@ ox::Error StudioUI::closeFile(ox::CRStringView path) noexcept { } oxIgnoreError(m_openFiles.erase(std::remove(m_openFiles.begin(), m_openFiles.end(), path))); // save to config - studio::editConfig(&m_ctx->keelCtx, [&](StudioConfig *config) { + studio::editConfig(&keelCtx(*m_ctx), [&](StudioConfig *config) { oxIgnoreError(config->openFiles.erase(std::remove(config->openFiles.begin(), config->openFiles.end(), path))); }); return OxError(0); diff --git a/src/studio/modlib/include/studio/itemmaker.hpp b/src/studio/modlib/include/studio/itemmaker.hpp index 7e52533c..3e0b955a 100644 --- a/src/studio/modlib/include/studio/itemmaker.hpp +++ b/src/studio/modlib/include/studio/itemmaker.hpp @@ -33,7 +33,7 @@ class ItemMakerT: public ItemMaker { const T item; const ox::ClawFormat fmt; public: - constexpr explicit ItemMakerT( + constexpr ItemMakerT( ox::StringView pDisplayName, ox::StringView pParentDir, ox::StringView fileExt, @@ -64,7 +64,7 @@ class ItemMakerT: public ItemMaker { ox::Error write(turbine::Context *ctx, ox::CRStringView pName) const noexcept override { const auto path = ox::sfmt("/{}/{}.{}", parentDir, pName, fileExt); auto sctx = turbine::applicationData(*ctx); - keel::createUuidMapping(ctx->keelCtx, path, ox::UUID::generate().unwrap()); + keel::createUuidMapping(keelCtx(*ctx), path, ox::UUID::generate().unwrap()); return sctx->project->writeObj(path, item, fmt); } }; diff --git a/src/turbine/CMakeLists.txt b/src/turbine/CMakeLists.txt index de321b7d..130b119d 100644 --- a/src/turbine/CMakeLists.txt +++ b/src/turbine/CMakeLists.txt @@ -1,35 +1 @@ -add_library( - Turbine - event.cpp -) - -add_subdirectory(gba) -if(NOT TURBINE_BUILD_TYPE STREQUAL "GBA") - add_subdirectory(glfw) -endif() - -target_link_libraries( - Turbine PUBLIC - Keel -) - -install( - FILES - clipboard.hpp - config.hpp - context.hpp - event.hpp - gfx.hpp - input.hpp - turbine.hpp - DESTINATION - include/turbine -) - -install( - TARGETS - Turbine - DESTINATION - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib -) +add_subdirectory(src) \ No newline at end of file diff --git a/src/turbine/clipboard.hpp b/src/turbine/clipboard.hpp deleted file mode 100644 index c6107c4f..00000000 --- a/src/turbine/clipboard.hpp +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved. - */ - -#pragma once - -#include -#include -#include - -#include "context.hpp" - -namespace turbine { - -ox::String getClipboardText(class Context &ctx) noexcept; - -void setClipboardText(class Context &ctx, ox::CRStringView text) noexcept; - -template -void setClipboardObject([[maybe_unused]] class Context &ctx, [[maybe_unused]] ox::UniquePtr obj) noexcept { - ctx.clipboard = std::move(obj); -} - -template -ox::Result getClipboardObject([[maybe_unused]] class Context &ctx) noexcept { - if (ctx.clipboard && ctx.clipboard->typeMatch(T::TypeName, T::TypeVersion)) { - return static_cast(ctx.clipboard.get()); - } - return OxError(1); -} - -} diff --git a/src/turbine/config.hpp b/src/turbine/config.hpp deleted file mode 100644 index dad2d9a1..00000000 --- a/src/turbine/config.hpp +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved. - */ - -#pragma once - -#if __has_include() -#endif - -#include - -namespace turbine::config { - -constexpr auto ImGuiEnabled = -#if __has_include() -true; -#else -false; -#endif - -constexpr auto GbaEventLoopTimerBased = false; -constexpr auto GbaTimerBits = 32; -constexpr auto GlFpsPrint = false; - -} diff --git a/src/turbine/context.hpp b/src/turbine/context.hpp deleted file mode 100644 index 48d4a219..00000000 --- a/src/turbine/context.hpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved. - */ - -#pragma once - -#include -#include -#include -#include - -#include - -#include "event.hpp" -#include "input.hpp" - -namespace turbine { - -class BaseClipboardObject { - public: - virtual ~BaseClipboardObject() noexcept = default; - - [[nodiscard]] - virtual ox::String typeId() const noexcept = 0; - - [[nodiscard]] - constexpr auto typeMatch(auto name, auto version) const noexcept { - return typeId() == ox::buildTypeId(name, version); - } -}; - -template -class ClipboardObject: public BaseClipboardObject { - [[nodiscard]] - ox::String typeId() const noexcept final { - return ox::buildTypeId(T::TypeName, T::TypeVersion); - } -}; - -void shutdown(Context &ctx) noexcept; - -// User Input Output -class Context { - friend constexpr void setApplicationData(Context &ctx, void *applicationData) noexcept; - template - friend constexpr T *applicationData(Context &ctx) noexcept; - friend void setUpdateHandler(Context &ctx, UpdateHandler h) noexcept; - friend constexpr void setKeyEventHandler(Context &ctx, KeyEventHandler h) noexcept; - friend constexpr KeyEventHandler keyEventHandler(Context &ctx) noexcept; - - public: - UpdateHandler updateHandler = [](Context&) -> int {return 0;}; - ox::UPtr clipboard; - keel::Context keelCtx; - - protected: - KeyEventHandler m_keyEventHandler = nullptr; - void *m_applicationData = nullptr; - - Context() noexcept = default; - - public: - Context(Context &other) noexcept = delete; - Context(const Context &other) noexcept = delete; - Context(const Context &&other) noexcept = delete; - - virtual inline ~Context() noexcept { - shutdown(*this); - } - -}; - -constexpr auto *rom(Context &ctx) noexcept { - return ctx.keelCtx.rom.get(); -} - -constexpr const auto *rom(const Context &ctx) noexcept { - return ctx.keelCtx.rom.get(); -} - -constexpr void setApplicationData(Context &ctx, void *applicationData) noexcept { - ctx.m_applicationData = applicationData; -} - -template -[[nodiscard]] -constexpr T *applicationData(Context &ctx) noexcept { - return static_cast(ctx.m_applicationData); -} - -constexpr void setKeyEventHandler(Context &ctx, KeyEventHandler h) noexcept { - ctx.m_keyEventHandler = h; -} - -constexpr KeyEventHandler keyEventHandler(Context &ctx) noexcept { - return ctx.m_keyEventHandler; -} - -void setConstantRefresh(Context &ctx, bool r) noexcept; - -} - diff --git a/src/turbine/gba/context.hpp b/src/turbine/gba/context.hpp deleted file mode 100644 index 8eba212e..00000000 --- a/src/turbine/gba/context.hpp +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved. - */ - -#pragma once - -#include -#include -#include -#include - -#include - -#include "../context.hpp" - -namespace turbine::gba { - -class Context: public turbine::Context { - public: - bool running = true; - - Context() noexcept = default; - Context(Context &other) noexcept = delete; - Context(const Context &other) noexcept = delete; - Context(const Context &&other) noexcept = delete; -}; - -} - diff --git a/src/turbine/glfw/CMakeLists.txt b/src/turbine/glfw/CMakeLists.txt deleted file mode 100644 index abddf74e..00000000 --- a/src/turbine/glfw/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -target_sources( - Turbine PRIVATE - clipboard.cpp - gfx.cpp - turbine.cpp -) -target_link_libraries( - Turbine PUBLIC - glad - glfw - imgui -) diff --git a/src/turbine/glfw/clipboard.cpp b/src/turbine/glfw/clipboard.cpp deleted file mode 100644 index 8fbf122b..00000000 --- a/src/turbine/glfw/clipboard.cpp +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved. - */ - -#include - -#include - -#include - -#include "context.hpp" - -namespace turbine { - -ox::String getClipboardText(Context &ctx) noexcept { - auto &gctx = static_cast(ctx); - return ox::String(glfwGetClipboardString(gctx.window)); -} - -void setClipboardText(Context &ctx, ox::CRStringView text) noexcept { - auto &gctx = static_cast(ctx); - auto cstr = ox_malloca(text.bytes() + 1, char); - ox_strncpy(cstr.get(), text.data(), text.bytes()); - glfwSetClipboardString(gctx.window, cstr.get()); -} - -} diff --git a/src/turbine/glfw/context.hpp b/src/turbine/glfw/context.hpp deleted file mode 100644 index 65e9bd22..00000000 --- a/src/turbine/glfw/context.hpp +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved. - */ - -#pragma once - -#include - -namespace turbine { - -struct GlfwContext: public turbine::Context { - int uninterruptedRefreshes = 3; - ox::UPtr clipboard; - struct GLFWwindow *window = nullptr; - // sets screen refresh to constant instead of only on event - bool constantRefresh = true; - ox::Vector drawers; - int64_t startTime = 0; - uint64_t wakeupTime = 0; - uint64_t keysDown = 0; - uint64_t prevFpsCheckTime = 0; - uint64_t draws = 0; -}; - -} diff --git a/src/turbine/glfw/turbine.cpp b/src/turbine/glfw/turbine.cpp deleted file mode 100644 index 829c4630..00000000 --- a/src/turbine/glfw/turbine.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved. - */ - -#include -#include -#include - -#include -#include - -#include "../config.hpp" -#include "context.hpp" - -namespace turbine { - -static void draw(GlfwContext &gctx) noexcept { - // draw start - if constexpr(turbine::config::ImGuiEnabled) { - ImGui_ImplOpenGL3_NewFrame(); - ImGui_ImplGlfw_NewFrame(); - ImGui::NewFrame(); - } - for (auto d : gctx.drawers) { - d->draw(gctx); - } - if constexpr(turbine::config::ImGuiEnabled) { - ImGui::Render(); - ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); - } - // draw end - glfwSwapBuffers(gctx.window); -} - -static void draw(GLFWwindow *window, int, int) noexcept { - auto &gctx = *static_cast(glfwGetWindowUserPointer(window)); - draw(gctx); -} - -ox::Result> init(ox::UPtr fs, ox::CRStringView appName) noexcept { - auto ctx = ox::make_unique(); - oxReturnError(keel::init(ctx->keelCtx, std::move(fs), appName)); - using namespace std::chrono; - ctx->startTime = duration_cast(system_clock::now().time_since_epoch()).count(); - glfwInit(); - oxReturnError(initGfx(*ctx)); - glfwSetWindowSizeCallback(ctx->window, draw); - return ox::UPtr(ctx.release()); -} - -static void tickFps(GlfwContext &gctx, uint64_t nowMs) noexcept { - ++gctx.draws; - if (gctx.draws >= 500) { - const auto duration = static_cast(nowMs - gctx.prevFpsCheckTime) / 1000.0; - const auto fps = static_cast(static_cast(gctx.draws) / duration); - if constexpr(config::GlFpsPrint) { - oxOutf("FPS: {}\n", fps); - } - oxTracef("turbine.fps", "FPS: {}", fps); - gctx.prevFpsCheckTime = nowMs; - gctx.draws = 0; - } -} - -ox::Error run(Context &ctx) noexcept { - auto &gctx = static_cast(ctx); - int sleepTime = 0; - while (!glfwWindowShouldClose(gctx.window)) { - glfwPollEvents(); - const auto ticks = ticksMs(gctx); - if (gctx.wakeupTime <= ticks) { - sleepTime = gctx.updateHandler(gctx); - if (sleepTime >= 0) { - gctx.wakeupTime = ticks + static_cast(sleepTime); - } else { - gctx.wakeupTime = ~uint64_t(0); - } - } else { - sleepTime = 10; - } - tickFps(gctx, ticks); - draw(gctx); - if (!gctx.constantRefresh) { - if (gctx.uninterruptedRefreshes) { - --gctx.uninterruptedRefreshes; - } else { - glfwWaitEventsTimeout(sleepTime); - } - } - } - shutdown(gctx); - return {}; -} - -void shutdown(Context &ctx) noexcept { - auto &gctx = static_cast(ctx); - if (gctx.window) { - ImGui_ImplOpenGL3_Shutdown(); - ImGui_ImplGlfw_Shutdown(); - glfwDestroyWindow(gctx.window); - gctx.window = nullptr; - } -} - -uint64_t ticksMs(const Context &ctx) noexcept { - using namespace std::chrono; - auto &gctx = static_cast(ctx); - const auto now = duration_cast(system_clock::now().time_since_epoch()).count(); - return static_cast(now - gctx.startTime); -} - -bool buttonDown(const Context &ctx, Key key) noexcept { - auto &gctx = static_cast(ctx); - return (gctx.keysDown >> static_cast(key)) & 1; -} - -void requestShutdown(Context &ctx) noexcept { - auto &gctx = static_cast(ctx); - glfwSetWindowShouldClose(gctx.window, true); -} - -} diff --git a/src/turbine/include/turbine/clipboard.hpp b/src/turbine/include/turbine/clipboard.hpp new file mode 100644 index 00000000..a9e5e9d0 --- /dev/null +++ b/src/turbine/include/turbine/clipboard.hpp @@ -0,0 +1,50 @@ +/* + * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved. + */ + +#pragma once + +#include +#include +#include + +#include "context.hpp" + +namespace turbine { + +class BaseClipboardObject { + public: + virtual ~BaseClipboardObject() noexcept = default; + + [[nodiscard]] + virtual ox::String typeId() const noexcept = 0; + + [[nodiscard]] + constexpr auto typeMatch(auto name, auto version) const noexcept { + return typeId() == ox::buildTypeId(name, version); + } +}; + +template +class ClipboardObject: public BaseClipboardObject { + [[nodiscard]] + ox::String typeId() const noexcept final { + return ox::buildTypeId(T::TypeName, T::TypeVersion); + } +}; + +ox::String getClipboardText(Context &ctx) noexcept; + +void setClipboardText(Context &ctx, ox::CRStringView text) noexcept; + +void setClipboardObject(Context &ctx, ox::UniquePtr &&obj) noexcept; + +ox::Result getClipboardData(Context &ctx, ox::StringView typeName, int typeVersion) noexcept; + +template +ox::Result getClipboardObject(Context &ctx) noexcept { + oxRequire(p, getClipboardData(ctx, T::TypeName, T::TypeVersion)); + return dynamic_cast(p); +} + +} diff --git a/src/turbine/include/turbine/context.hpp b/src/turbine/include/turbine/context.hpp new file mode 100644 index 00000000..3d5bca4c --- /dev/null +++ b/src/turbine/include/turbine/context.hpp @@ -0,0 +1,56 @@ +/* + * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved. + */ + +#pragma once + +#include +#include +#include +#include + +#include + +#include "input.hpp" + +namespace turbine { + +class Context; + +struct ContextDeleter { + void operator()(Context *p) noexcept; +}; + +using ContextUPtr = ox::UPtr; + +void shutdown(Context &ctx) noexcept; + +keel::Context const&keelCtx(Context const&ctx) noexcept; + +keel::Context &keelCtx(Context &ctx) noexcept; + +inline ox::FileSystem const*rom(Context const&ctx) noexcept { + return keelCtx(ctx).rom.get(); +} + +inline ox::FileSystem *rom(Context &ctx) noexcept { + return keelCtx(ctx).rom.get(); +} + +void setApplicationData(Context &ctx, void *applicationData) noexcept; + +[[nodiscard]] +void *applicationDataRaw(Context &ctx) noexcept; + +template +[[nodiscard]] +T *applicationData(Context &ctx) noexcept { + return static_cast(applicationDataRaw(ctx)); +} + +void setKeyEventHandler(Context &ctx, KeyEventHandler h) noexcept; + +KeyEventHandler keyEventHandler(Context &ctx) noexcept; + +} + diff --git a/src/turbine/event.hpp b/src/turbine/include/turbine/event.hpp similarity index 100% rename from src/turbine/event.hpp rename to src/turbine/include/turbine/event.hpp diff --git a/src/turbine/gfx.hpp b/src/turbine/include/turbine/gfx.hpp similarity index 87% rename from src/turbine/gfx.hpp rename to src/turbine/include/turbine/gfx.hpp index f57a06bd..f52d4472 100644 --- a/src/turbine/gfx.hpp +++ b/src/turbine/include/turbine/gfx.hpp @@ -41,6 +41,8 @@ ox::Size getScreenSize(Context &ctx) noexcept; ox::Bounds getWindowBounds(Context &ctx) noexcept; -ox::Error setWindowBounds(Context &ctx, const ox::Bounds &bnds) noexcept; +ox::Error setWindowBounds(Context &ctx, ox::Bounds const&bnds) noexcept; + +void setConstantRefresh(Context &ctx, bool r) noexcept; } diff --git a/src/turbine/input.hpp b/src/turbine/include/turbine/input.hpp similarity index 94% rename from src/turbine/input.hpp rename to src/turbine/include/turbine/input.hpp index 15f65d67..43c733ed 100644 --- a/src/turbine/input.hpp +++ b/src/turbine/include/turbine/input.hpp @@ -72,7 +72,7 @@ enum Key { class Context; [[nodiscard]] -bool buttonDown(const Context &ctx, Key) noexcept; +bool buttonDown(Context const&ctx, Key) noexcept; using KeyEventHandler = void(*)(Context&, Key, bool); diff --git a/src/turbine/turbine.hpp b/src/turbine/include/turbine/turbine.hpp similarity index 68% rename from src/turbine/turbine.hpp rename to src/turbine/include/turbine/turbine.hpp index bf54fab9..6d390d94 100644 --- a/src/turbine/turbine.hpp +++ b/src/turbine/include/turbine/turbine.hpp @@ -4,6 +4,7 @@ #pragma once +#include #include #include "clipboard.hpp" @@ -13,16 +14,14 @@ namespace turbine { -ox::Result> init(ox::UniquePtr fs, ox::CRStringView appName) noexcept; - -void shutdown(Context &ctx) noexcept; +ox::Result init(ox::UPtr &&fs, ox::CRStringView appName) noexcept; ox::Error run(Context &ctx) noexcept; // Returns the number of milliseconds that have passed since the start of the // program. [[nodiscard]] -uint64_t ticksMs(const Context &ctx) noexcept; +uint64_t ticksMs(Context const&ctx) noexcept; void requestShutdown(Context &ctx) noexcept; diff --git a/src/turbine/src/CMakeLists.txt b/src/turbine/src/CMakeLists.txt new file mode 100644 index 00000000..1e9a57c6 --- /dev/null +++ b/src/turbine/src/CMakeLists.txt @@ -0,0 +1,40 @@ +add_library(Turbine) + +set(TURBINE_BACKEND_GBA ${TURBINE_BUILD_TYPE} STREQUAL "GBA") +set(TURBINE_BACKEND_GLFW NOT ${TURBINE_BACKEND_GBA}) + +add_subdirectory(gba) +if(${TURBINE_BACKEND_GLFW}) + add_subdirectory(glfw) +endif() + +target_include_directories( + Turbine PUBLIC + ../include +) + +target_link_libraries( + Turbine PUBLIC + Keel +) + +target_compile_definitions( + Turbine PRIVATE + TURBINE_BACKEND_GBA=$,1,0> + TURBINE_BACKEND_GLFW=$,1,0> +) + +install( + DIRECTORY + ../include/turbine + DESTINATION + include/turbine +) + +install( + TARGETS + Turbine + DESTINATION + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib +) diff --git a/src/turbine/gba/CMakeLists.txt b/src/turbine/src/gba/CMakeLists.txt similarity index 53% rename from src/turbine/gba/CMakeLists.txt rename to src/turbine/src/gba/CMakeLists.txt index 7bdc8926..3491f148 100644 --- a/src/turbine/gba/CMakeLists.txt +++ b/src/turbine/src/gba/CMakeLists.txt @@ -1,13 +1,24 @@ +option(TURBINE_GBA_EVENT_LOOP_TIMER_BASED "Run event loop on time instead of vsync" OFF) +set(TURBINE_GBA_TIMER_BITS "32" CACHE STRING "Bits for system time (16, 32, 64)") + add_library(Turbine-GBA OBJECT) target_sources( Turbine-GBA PRIVATE + context.cpp clipboard.cpp + event.cpp gfx.cpp irq.arm.cpp turbine.arm.cpp turbine.cpp ) +target_compile_definitions( + Turbine-GBA PRIVATE + TURBINE_GBA_EVENT_LOOP_TIMER_BASED=$,true,false> + TURBINE_GBA_TIMER_BITS=${TURBINE_GBA_TIMER_BITS} +) + if(TURBINE_BUILD_TYPE STREQUAL "GBA") enable_language(ASM) set_source_files_properties(turbine.arm.cpp irq.arm.cpp PROPERTIES COMPILE_FLAGS -marm) @@ -23,6 +34,11 @@ else() ) endif() +target_include_directories( + Turbine-GBA PUBLIC + ../../include +) + target_link_libraries( Turbine-GBA PUBLIC TeaGBA diff --git a/src/turbine/gba/clipboard.cpp b/src/turbine/src/gba/clipboard.cpp similarity index 99% rename from src/turbine/gba/clipboard.cpp rename to src/turbine/src/gba/clipboard.cpp index 947ce099..a00e0d36 100644 --- a/src/turbine/gba/clipboard.cpp +++ b/src/turbine/src/gba/clipboard.cpp @@ -13,7 +13,6 @@ ox::String getClipboardText(Context&) noexcept { } void setClipboardText(Context&, ox::CRStringView) noexcept { - } } diff --git a/src/turbine/src/gba/config.hpp b/src/turbine/src/gba/config.hpp new file mode 100644 index 00000000..cec7abe2 --- /dev/null +++ b/src/turbine/src/gba/config.hpp @@ -0,0 +1,12 @@ +/* + * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved. + */ + +#pragma once + +namespace turbine::config { + +constexpr bool GbaEventLoopTimerBased = TURBINE_GBA_EVENT_LOOP_TIMER_BASED; +constexpr int GbaTimerBits = TURBINE_GBA_TIMER_BITS; + +} diff --git a/src/turbine/src/gba/context.cpp b/src/turbine/src/gba/context.cpp new file mode 100644 index 00000000..402c10d0 --- /dev/null +++ b/src/turbine/src/gba/context.cpp @@ -0,0 +1,29 @@ +/* + * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved. + */ + +#include "context.hpp" + +namespace turbine { + +void ContextDeleter::operator()(Context *p) noexcept { + ox::safeDelete(p); +} + +keel::Context const&keelCtx(Context const&ctx) noexcept { + return ctx.keelCtx; +} + +keel::Context &keelCtx(Context &ctx) noexcept { + return ctx.keelCtx; +} + +void setApplicationData(Context &ctx, void *applicationData) noexcept { + ctx.applicationData = applicationData; +} + +void *applicationDataRaw(Context &ctx) noexcept { + return ctx.applicationData; +} + +} diff --git a/src/turbine/src/gba/context.hpp b/src/turbine/src/gba/context.hpp new file mode 100644 index 00000000..430b9bc3 --- /dev/null +++ b/src/turbine/src/gba/context.hpp @@ -0,0 +1,36 @@ +/* + * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved. + */ + +#pragma once + +#include + +#include +#include +#include + +namespace turbine { + +class Context { + public: + UpdateHandler updateHandler = [](Context&) -> int {return 0;}; + keel::Context keelCtx; + KeyEventHandler keyEventHandler = nullptr; + void *applicationData = nullptr; + + // GBA impl data ///////////////////////////////////////////////////////// + bool running = true; + + Context() noexcept = default; + Context(Context &other) noexcept = delete; + Context(Context const&other) noexcept = delete; + Context(Context const&&other) noexcept = delete; + + virtual inline ~Context() noexcept { + shutdown(*this); + } + +}; + +} diff --git a/src/turbine/event.cpp b/src/turbine/src/gba/event.cpp similarity index 50% rename from src/turbine/event.cpp rename to src/turbine/src/gba/event.cpp index d0f3c04c..75b2fca9 100644 --- a/src/turbine/event.cpp +++ b/src/turbine/src/gba/event.cpp @@ -2,8 +2,9 @@ * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved. */ +#include + #include "context.hpp" -#include "event.hpp" namespace turbine { @@ -11,4 +12,12 @@ void setUpdateHandler(Context &ctx, UpdateHandler h) noexcept { ctx.updateHandler = h; } -} \ No newline at end of file +void setKeyEventHandler(Context &ctx, KeyEventHandler h) noexcept { + ctx.keyEventHandler = h; +} + +KeyEventHandler keyEventHandler(Context &ctx) noexcept { + return ctx.keyEventHandler; +} + +} diff --git a/src/turbine/gba/gfx.cpp b/src/turbine/src/gba/gfx.cpp similarity index 94% rename from src/turbine/gba/gfx.cpp rename to src/turbine/src/gba/gfx.cpp index 3ffacbdf..daa3429f 100644 --- a/src/turbine/gba/gfx.cpp +++ b/src/turbine/src/gba/gfx.cpp @@ -43,7 +43,7 @@ ox::Bounds getWindowBounds(Context&) noexcept { return {0, 0, 240, 160}; } -ox::Error setWindowBounds(Context&, const ox::Bounds&) noexcept { +ox::Error setWindowBounds(Context&, ox::Bounds const&) noexcept { return OxError(1, "setWindowBounds not supported on GBA"); } diff --git a/src/turbine/gba/irq.arm.cpp b/src/turbine/src/gba/irq.arm.cpp similarity index 100% rename from src/turbine/gba/irq.arm.cpp rename to src/turbine/src/gba/irq.arm.cpp diff --git a/src/turbine/gba/irq.s b/src/turbine/src/gba/irq.s similarity index 100% rename from src/turbine/gba/irq.s rename to src/turbine/src/gba/irq.s diff --git a/src/turbine/gba/irqstub.cpp b/src/turbine/src/gba/irqstub.cpp similarity index 100% rename from src/turbine/gba/irqstub.cpp rename to src/turbine/src/gba/irqstub.cpp diff --git a/src/turbine/gba/turbine.arm.cpp b/src/turbine/src/gba/turbine.arm.cpp similarity index 91% rename from src/turbine/gba/turbine.arm.cpp rename to src/turbine/src/gba/turbine.arm.cpp index 73530256..fc9610ec 100644 --- a/src/turbine/gba/turbine.arm.cpp +++ b/src/turbine/src/gba/turbine.arm.cpp @@ -16,8 +16,7 @@ static gba_timer_t g_wakeupTime{}; ox::Error run(Context &ctx) noexcept { g_wakeupTime = 0; - const auto gbaCtx = static_cast(&ctx); - while (gbaCtx->running) { + while (ctx.running) { if (g_wakeupTime <= g_timerMs && ctx.updateHandler) { auto sleepTime = ctx.updateHandler(ctx); if (sleepTime >= 0) { diff --git a/src/turbine/gba/turbine.cpp b/src/turbine/src/gba/turbine.cpp similarity index 80% rename from src/turbine/gba/turbine.cpp rename to src/turbine/src/gba/turbine.cpp index 0fb1ddba..860f9de2 100644 --- a/src/turbine/gba/turbine.cpp +++ b/src/turbine/src/gba/turbine.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include "context.hpp" @@ -46,16 +47,17 @@ static ox::Result findPreloadSection() noexcept { constexpr auto headerP2Len = ox_strlen(headerP1); constexpr auto headerLen = headerP1Len + headerP2Len; for (auto current = MEM_ROM; current < reinterpret_cast(0x0a000000); current += headerLen) { - if (ox_memcmp(current, headerP1, headerP1Len) == 0 && - ox_memcmp(current + headerP1Len, headerP2, headerP2Len) == 0) { + if (memcmp(current, headerP1, headerP1Len) == 0 && + memcmp(current + headerP1Len, headerP2, headerP2Len) == 0) { return reinterpret_cast(current + headerLen); } } return OxError(1); } -ox::Result> init(ox::UPtr fs, ox::CRStringView appName) noexcept { - auto ctx = ox::make_unique(); +ox::Result init( + ox::UPtr &&fs, ox::CRStringView appName) noexcept { + auto ctx = ox::make_unique(); oxReturnError(keel::init(ctx->keelCtx, std::move(fs), appName)); #ifdef OX_BARE_METAL oxReturnError(findPreloadSection().moveTo(&ctx->keelCtx.preloadSectionOffset)); @@ -63,7 +65,7 @@ ox::Result> init(ox::UPtr fs, ox oxReturnError(initGfx(*ctx)); initTimer(); initIrq(); - return ox::UPtr(std::move(ctx)); + return ox::UPtr(std::move(ctx)); } void shutdown(Context&) noexcept { @@ -73,13 +75,12 @@ uint64_t ticksMs(Context&) noexcept { return g_timerMs; } -bool buttonDown(Context&, Key k) noexcept { +bool buttonDown(Context const&, Key k) noexcept { return k <= Key::GamePad_L && !(REG_GAMEPAD & (1 << static_cast(k))); } void requestShutdown(Context &ctx) noexcept { - const auto gbaCtx = static_cast(&ctx); - gbaCtx->running = false; + ctx.running = false; } } diff --git a/src/turbine/gba/turbine.hpp b/src/turbine/src/gba/turbine.hpp similarity index 89% rename from src/turbine/gba/turbine.hpp rename to src/turbine/src/gba/turbine.hpp index f41b7234..894d72b0 100644 --- a/src/turbine/gba/turbine.hpp +++ b/src/turbine/src/gba/turbine.hpp @@ -6,7 +6,7 @@ #include -#include "../config.hpp" +#include "config.hpp" namespace turbine { diff --git a/src/turbine/src/glfw/CMakeLists.txt b/src/turbine/src/glfw/CMakeLists.txt new file mode 100644 index 00000000..47f7885e --- /dev/null +++ b/src/turbine/src/glfw/CMakeLists.txt @@ -0,0 +1,24 @@ +option(TURBINE_USE_IMGUI "Include DearImGUI in build (GLFW only)" ON) +option(TURBINE_GL_FPS_PRINT "Print FPS to stdout" OFF) + +target_sources( + Turbine PRIVATE + context.cpp + clipboard.cpp + event.cpp + gfx.cpp + turbine.cpp +) + +target_compile_definitions( + Turbine PRIVATE + TURBINE_USE_IMGUI=$,1,0> + TURBINE_GL_FPS_PRINT=$,true,false> +) + +target_link_libraries( + Turbine PUBLIC + glad + glfw + imgui +) diff --git a/src/turbine/src/glfw/clipboard.cpp b/src/turbine/src/glfw/clipboard.cpp new file mode 100644 index 00000000..5bbb1fe5 --- /dev/null +++ b/src/turbine/src/glfw/clipboard.cpp @@ -0,0 +1,36 @@ +/* + * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved. + */ + +#include + +#include + +#include + +#include "context.hpp" + +namespace turbine { + +ox::String getClipboardText(Context &ctx) noexcept { + return ox::String(glfwGetClipboardString(ctx.window)); +} + +void setClipboardText(Context &ctx, ox::CRStringView text) noexcept { + auto cstr = ox_malloca(text.bytes() + 1, char); + ox_strncpy(cstr.get(), text.data(), text.bytes()); + glfwSetClipboardString(ctx.window, cstr.get()); +} + +void setClipboardObject(Context &ctx, ox::UniquePtr &&obj) noexcept { + ctx.clipboard = std::move(obj); +} + +ox::Result getClipboardData(Context &ctx, ox::StringView typeName, int typeVersion) noexcept { + if (ctx.clipboard && ctx.clipboard->typeMatch(typeName, typeVersion)) { + return ctx.clipboard.get(); + } + return OxError(1); +} + +} diff --git a/src/turbine/src/glfw/config.hpp b/src/turbine/src/glfw/config.hpp new file mode 100644 index 00000000..974e1f01 --- /dev/null +++ b/src/turbine/src/glfw/config.hpp @@ -0,0 +1,11 @@ +/* + * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved. + */ + +#pragma once + +namespace turbine::config { + +constexpr bool GlFpsPrint = TURBINE_GL_FPS_PRINT; + +} diff --git a/src/turbine/src/glfw/context.cpp b/src/turbine/src/glfw/context.cpp new file mode 100644 index 00000000..c988f0fb --- /dev/null +++ b/src/turbine/src/glfw/context.cpp @@ -0,0 +1,31 @@ +/* + * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved. + */ + +#include + +#include "context.hpp" + +namespace turbine { + +void ContextDeleter::operator()(Context *p) noexcept { + ox::safeDelete(p); +} + +keel::Context const&keelCtx(Context const&ctx) noexcept { + return ctx.keelCtx; +} + +keel::Context &keelCtx(Context &ctx) noexcept { + return ctx.keelCtx; +} + +void setApplicationData(Context &ctx, void *applicationData) noexcept { + ctx.applicationData = applicationData; +} + +void *applicationDataRaw(Context &ctx) noexcept { + return ctx.applicationData; +} + +} diff --git a/src/turbine/src/glfw/context.hpp b/src/turbine/src/glfw/context.hpp new file mode 100644 index 00000000..d654a0b6 --- /dev/null +++ b/src/turbine/src/glfw/context.hpp @@ -0,0 +1,41 @@ +/* + * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved. + */ + +#pragma once + +#include +#include +#include +#include + +namespace turbine { + +class Context { + public: + UpdateHandler updateHandler = [](Context&) -> int {return 0;}; + keel::Context keelCtx; + KeyEventHandler keyEventHandler = nullptr; + void *applicationData = nullptr; + + // GLFW impl data //////////////////////////////////////////////////////// + int uninterruptedRefreshes = 3; + ox::UPtr clipboard; + struct GLFWwindow *window = nullptr; + // sets screen refresh to constant instead of only on event + bool constantRefresh = true; + ox::Vector drawers; + int64_t startTime = 0; + uint64_t wakeupTime = 0; + uint64_t keysDown = 0; + uint64_t prevFpsCheckTime = 0; + uint64_t draws = 0; + + Context() noexcept = default; + + Context(Context const&other) noexcept = delete; + Context(Context const&&other) noexcept = delete; + +}; + +} diff --git a/src/turbine/src/glfw/event.cpp b/src/turbine/src/glfw/event.cpp new file mode 100644 index 00000000..75b2fca9 --- /dev/null +++ b/src/turbine/src/glfw/event.cpp @@ -0,0 +1,23 @@ +/* + * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved. + */ + +#include + +#include "context.hpp" + +namespace turbine { + +void setUpdateHandler(Context &ctx, UpdateHandler h) noexcept { + ctx.updateHandler = h; +} + +void setKeyEventHandler(Context &ctx, KeyEventHandler h) noexcept { + ctx.keyEventHandler = h; +} + +KeyEventHandler keyEventHandler(Context &ctx) noexcept { + return ctx.keyEventHandler; +} + +} diff --git a/src/turbine/glfw/gfx.cpp b/src/turbine/src/glfw/gfx.cpp similarity index 78% rename from src/turbine/glfw/gfx.cpp rename to src/turbine/src/glfw/gfx.cpp index da5f85d4..9c156579 100644 --- a/src/turbine/glfw/gfx.cpp +++ b/src/turbine/src/glfw/gfx.cpp @@ -4,38 +4,27 @@ #include #include +#if TURBINE_USE_IMGUI #include #include +#endif #include -#include - #include "context.hpp" namespace turbine { -[[nodiscard]] -inline GlfwContext &glctx(Context &ctx) noexcept { - if constexpr(ox::defines::Debug) { - return dynamic_cast(ctx); - } else { - return static_cast(ctx); - } -} - namespace gl { void addDrawer(Context &ctx, Drawer *cd) noexcept { - auto &gctx = glctx(ctx); - gctx.drawers.emplace_back(cd); + ctx.drawers.emplace_back(cd); } void removeDrawer(Context &ctx, Drawer *cd) noexcept { - auto &gctx = glctx(ctx); - for (auto i = 0u; i < gctx.drawers.size(); ++i) { - if (gctx.drawers[i] == cd) { - oxIgnoreError(gctx.drawers.erase(i)); + for (auto i = 0u; i < ctx.drawers.size(); ++i) { + if (ctx.drawers[i] == cd) { + oxIgnoreError(ctx.drawers.erase(i)); break; } } @@ -47,15 +36,12 @@ static void handleGlfwError(int err, const char *desc) noexcept { oxErrf("GLFW error ({}): {}\n", err, desc); } -static auto setKeyDownStatus(GlfwContext *gctx, Key key, bool down) noexcept { - if (down) { - gctx->keysDown |= 1llu << static_cast(key); - } else { - gctx->keysDown &= ~(1llu << static_cast(key)); - } +static auto setKeyDownStatus(Context &ctx, Key key, bool down) noexcept { + ctx.keysDown &= ~(1llu << static_cast(key)); + ctx.keysDown |= static_cast(down) << static_cast(key); } -static void handleKeyPress(Context *ctx, int key, bool down) noexcept { +static void handleKeyPress(Context &ctx, int key, bool down) noexcept { static constexpr auto keyMap = [] { ox::Array map = {}; for (auto i = 0u; i < 26; ++i) { @@ -73,12 +59,11 @@ static void handleKeyPress(Context *ctx, int key, bool down) noexcept { map[GLFW_KEY_ESCAPE] = Key::Escape; return map; }(); - const auto eventHandler = keyEventHandler(*ctx); - auto &gctx = glctx(*ctx); + const auto eventHandler = keyEventHandler(ctx); const auto k = keyMap[static_cast(key)]; - setKeyDownStatus(&gctx, k, down); + setKeyDownStatus(ctx, k, down); if (eventHandler) { - eventHandler(*ctx, k, down); + eventHandler(ctx, k, down); } //if constexpr(ox::defines::Debug) { // switch (key) { @@ -96,20 +81,21 @@ static void handleGlfwCursorPosEvent(GLFWwindow*, double, double) noexcept { } static void handleGlfwMouseButtonEvent(GLFWwindow *window, int, int, int) noexcept { - const auto ctx = static_cast(glfwGetWindowUserPointer(window)); + const auto ctx = static_cast(glfwGetWindowUserPointer(window)); ctx->uninterruptedRefreshes = 25; } static void handleGlfwKeyEvent(GLFWwindow *window, int key, int, int action, int) noexcept { - const auto ctx = static_cast(glfwGetWindowUserPointer(window)); + const auto ctx = static_cast(glfwGetWindowUserPointer(window)); ctx->uninterruptedRefreshes = 25; if (action == GLFW_PRESS) { - handleKeyPress(ctx, key, true); + handleKeyPress(*ctx, key, true); } else if (action == GLFW_RELEASE) { - handleKeyPress(ctx, key, false); + handleKeyPress(*ctx, key, false); } } +#if TURBINE_USE_IMGUI static void themeImgui() noexcept { // Dark Ruda style by Raikiri from ImThemes auto &style = ImGui::GetStyle(); @@ -207,9 +193,9 @@ static void themeImgui() noexcept { style.Colors[ImGuiCol_NavWindowingDimBg] = imVec4(0.800000011920929, 0.800000011920929, 0.800000011920929, 0.2000000029802322); style.Colors[ImGuiCol_ModalWindowDimBg] = imVec4(0.800000011920929, 0.800000011920929, 0.800000011920929, 0.3499999940395355); } +#endif ox::Error initGfx(Context &ctx) noexcept { - auto &gctx = glctx(ctx); glfwSetErrorCallback(handleGlfwError); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); @@ -218,86 +204,76 @@ ox::Error initGfx(Context &ctx) noexcept { glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE); } glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); - auto cstr = ox_malloca(ctx.keelCtx.appName.bytes() + 1, char); - ox_strncpy(cstr.get(), ctx.keelCtx.appName.data(), ctx.keelCtx.appName.bytes()); constexpr auto Scale = 5; - gctx.window = glfwCreateWindow(240 * Scale, 160 * Scale, cstr.get(), nullptr, nullptr); - //gctx.window = glfwCreateWindow(868, 741, cstr.get(), nullptr, nullptr); - if (gctx.window == nullptr) { + ctx.window = glfwCreateWindow(240 * Scale, 160 * Scale, ctx.keelCtx.appName.c_str(), nullptr, nullptr); + //ctx.window = glfwCreateWindow(876, 743, ctx.keelCtx.appName.c_str(), nullptr, nullptr); + if (ctx.window == nullptr) { return OxError(1, "Could not open GLFW window"); } - glfwSetCursorPosCallback(gctx.window, handleGlfwCursorPosEvent); - glfwSetMouseButtonCallback(gctx.window, handleGlfwMouseButtonEvent); - glfwSetKeyCallback(gctx.window, handleGlfwKeyEvent); - glfwSetWindowUserPointer(gctx.window, &ctx); - glfwMakeContextCurrent(gctx.window); + glfwSetCursorPosCallback(ctx.window, handleGlfwCursorPosEvent); + glfwSetMouseButtonCallback(ctx.window, handleGlfwMouseButtonEvent); + glfwSetKeyCallback(ctx.window, handleGlfwKeyEvent); + glfwSetWindowUserPointer(ctx.window, &ctx); + glfwMakeContextCurrent(ctx.window); if (!gladLoadGLES2Loader(reinterpret_cast(glfwGetProcAddress))) { return OxError(2, "Could not init Glad"); } - if constexpr(config::ImGuiEnabled) { - IMGUI_CHECKVERSION(); - ImGui::CreateContext(); - auto &io = ImGui::GetIO(); - io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; - //io.MouseDrawCursor = true; - ImGui_ImplGlfw_InitForOpenGL(gctx.window, true); - ImGui_ImplOpenGL3_Init(); - themeImgui(); - } +#if TURBINE_USE_IMGUI + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + auto &io = ImGui::GetIO(); + io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; + //io.MouseDrawCursor = true; + ImGui_ImplGlfw_InitForOpenGL(ctx.window, true); + ImGui_ImplOpenGL3_Init(); + themeImgui(); +#endif return {}; } void setWindowTitle(Context &ctx, ox::CRStringView title) noexcept { - auto &gctx = glctx(ctx); auto cstr = ox_malloca(title.bytes() + 1, char); ox_strncpy(cstr.get(), title.data(), title.bytes()); - glfwSetWindowTitle(gctx.window, cstr.get()); + glfwSetWindowTitle(ctx.window, cstr.get()); } void focusWindow(Context &ctx) noexcept { - auto &gctx = glctx(ctx); - glfwFocusWindow(gctx.window); + glfwFocusWindow(ctx.window); } int getScreenWidth(Context &ctx) noexcept { - auto &gctx = glctx(ctx); int w = 0, h = 0; - glfwGetFramebufferSize(gctx.window, &w, &h); + glfwGetFramebufferSize(ctx.window, &w, &h); return w; } int getScreenHeight(Context &ctx) noexcept { - auto &gctx = glctx(ctx); int w = 0, h = 0; - glfwGetFramebufferSize(gctx.window, &w, &h); + glfwGetFramebufferSize(ctx.window, &w, &h); return h; } ox::Size getScreenSize(Context &ctx) noexcept { - auto &gctx = glctx(ctx); int w = 0, h = 0; - glfwGetFramebufferSize(gctx.window, &w, &h); + glfwGetFramebufferSize(ctx.window, &w, &h); return {w, h}; } ox::Bounds getWindowBounds(Context &ctx) noexcept { - auto &gctx = glctx(ctx); ox::Bounds bnds; - glfwGetWindowPos(gctx.window, &bnds.x, &bnds.y); - glfwGetWindowSize(gctx.window, &bnds.width, &bnds.height); + glfwGetWindowPos(ctx.window, &bnds.x, &bnds.y); + glfwGetWindowSize(ctx.window, &bnds.width, &bnds.height); return bnds; } -ox::Error setWindowBounds(Context &ctx, const ox::Bounds &bnds) noexcept { - auto &gctx = glctx(ctx); - glfwSetWindowPos(gctx.window, bnds.x, bnds.y); - glfwSetWindowSize(gctx.window, bnds.width, bnds.height); +ox::Error setWindowBounds(Context &ctx, ox::Bounds const&bnds) noexcept { + glfwSetWindowPos(ctx.window, bnds.x, bnds.y); + glfwSetWindowSize(ctx.window, bnds.width, bnds.height); return {}; } void setConstantRefresh(Context &ctx, bool r) noexcept { - auto &gctx = glctx(ctx); - gctx.constantRefresh = r; + ctx.constantRefresh = r; } } diff --git a/src/turbine/src/glfw/turbine.cpp b/src/turbine/src/glfw/turbine.cpp new file mode 100644 index 00000000..e0c8d31a --- /dev/null +++ b/src/turbine/src/glfw/turbine.cpp @@ -0,0 +1,123 @@ +/* + * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved. + */ + +#include +#if TURBINE_USE_IMGUI +#include +#include +#endif + +#include + +#include + +#include "config.hpp" +#include "context.hpp" + +namespace turbine { + +static void draw(Context &ctx) noexcept { + // draw start +#if TURBINE_USE_IMGUI + ImGui_ImplOpenGL3_NewFrame(); + ImGui_ImplGlfw_NewFrame(); + ImGui::NewFrame(); +#endif + for (auto d : ctx.drawers) { + d->draw(ctx); + } +#if TURBINE_USE_IMGUI + ImGui::Render(); + ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); +#endif + // draw end + glfwSwapBuffers(ctx.window); +} + +static void draw(GLFWwindow *window, int, int) noexcept { + auto &ctx = *static_cast(glfwGetWindowUserPointer(window)); + draw(ctx); +} + +ox::Result init( + ox::UPtr &&fs, ox::CRStringView appName) noexcept { + auto ctx = ox::make_unique(); + oxReturnError(keel::init(ctx->keelCtx, std::move(fs), appName)); + using namespace std::chrono; + ctx->startTime = duration_cast(system_clock::now().time_since_epoch()).count(); + glfwInit(); + oxReturnError(initGfx(*ctx)); + glfwSetWindowSizeCallback(ctx->window, draw); + return ox::UPtr(ctx.release()); +} + +static void tickFps(Context &ctx, uint64_t nowMs) noexcept { + ++ctx.draws; + if (ctx.draws >= 500) { + const auto duration = static_cast(nowMs - ctx.prevFpsCheckTime) / 1000.0; + const auto fps = static_cast(static_cast(ctx.draws) / duration); + if constexpr(config::GlFpsPrint) { + oxOutf("FPS: {}\n", fps); + } + oxTracef("turbine.fps", "FPS: {}", fps); + ctx.prevFpsCheckTime = nowMs; + ctx.draws = 0; + } +} + +ox::Error run(Context &ctx) noexcept { + int sleepTime = 0; + while (!glfwWindowShouldClose(ctx.window)) { + glfwPollEvents(); + const auto ticks = ticksMs(ctx); + if (ctx.wakeupTime <= ticks) { + sleepTime = ctx.updateHandler(ctx); + if (sleepTime >= 0) { + ctx.wakeupTime = ticks + static_cast(sleepTime); + } else { + ctx.wakeupTime = ~uint64_t(0); + } + } else { + sleepTime = 10; + } + tickFps(ctx, ticks); + draw(ctx); + if (!ctx.constantRefresh) { + if (ctx.uninterruptedRefreshes) { + --ctx.uninterruptedRefreshes; + } else { + glfwWaitEventsTimeout(sleepTime); + } + } + } + shutdown(ctx); + return {}; +} + +void shutdown(Context &ctx) noexcept { + if (ctx.window) { +#if TURBINE_USE_IMGUI + ImGui_ImplOpenGL3_Shutdown(); + ImGui_ImplGlfw_Shutdown(); +#endif + glfwDestroyWindow(ctx.window); + ctx.window = nullptr; + } +} + +uint64_t ticksMs(Context const&ctx) noexcept { + using namespace std::chrono; + const auto now = duration_cast(system_clock::now().time_since_epoch()).count(); + return static_cast(now - ctx.startTime); +} + +bool buttonDown(Context const&ctx, Key key) noexcept { + return (ctx.keysDown >> static_cast(key)) & 1; +} + +void requestShutdown(Context &ctx) noexcept { + glfwSetWindowShouldClose(ctx.window, true); +} + +}