From a4a00c99d05441f5db491e06186039f817cb5c81 Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Sat, 17 May 2025 17:48:31 -0500 Subject: [PATCH] Squashed 'deps/nostalgia/' changes from 3ccadba2..cb304ecf cb304ecf [applib] Cleanup ea173777 [ox/std] Make StringViewCR honest c424bde0 [nostalgia] Style cleanup ee7d5c6d [nostalgia/gfx] Cleanup 99247cee [nostalgia/gfx/test] Cleanup 7b8ddc18 [nostalgia/gfx] Consolidate implementations into single files, remove unnecessary function exports a6814030 [studio/applib] Cleanup 9937a010 [turbine] Cleanup abcf2adc [nostalgia/gfx] Cleanup 05f90235 [nostalgia/gfx] Cleanup 5ba0bcf9 [turbine] Consolidate some files that didn't have sensible distinctions git-subtree-dir: deps/nostalgia git-subtree-split: cb304ecf2852db37a7aa7ca3bfc9d28877d5c1bd --- deps/ox/src/ox/std/stringview.hpp | 6 +- .../gfx/include/nostalgia/gfx/core.hpp | 14 - .../modules/gfx/include/nostalgia/gfx/gfx.hpp | 4 + .../gfx/include/nostalgia/gfx/keelmodule.hpp | 2 +- .../include/nostalgia/gfx/studiomodule.hpp | 2 +- src/nostalgia/modules/gfx/src/CMakeLists.txt | 40 ++- .../modules/gfx/src/gba/CMakeLists.txt | 21 -- src/nostalgia/modules/gfx/src/gba/context.cpp | 36 -- src/nostalgia/modules/gfx/src/gba/context.hpp | 34 -- src/nostalgia/modules/gfx/src/gba/gfx.hpp | 11 - src/nostalgia/modules/gfx/src/gba/panic.cpp | 58 ---- .../gfx/src/{gba/gfx.cpp => gfx-gba.cpp} | 84 ++++- .../src/{opengl/gfx.cpp => gfx-opengl.cpp} | 159 +++++++-- src/nostalgia/modules/gfx/src/gfx.cpp | 38 +- .../modules/gfx/src/opengl/CMakeLists.txt | 9 - .../modules/gfx/src/opengl/context.cpp | 40 --- .../modules/gfx/src/opengl/context.hpp | 40 --- src/nostalgia/modules/gfx/src/opengl/gfx.hpp | 65 ---- src/nostalgia/modules/gfx/test/tests.cpp | 10 +- .../include/nostalgia/sound/keelmodule.hpp | 2 +- .../include/nostalgia/sound/studiomodule.hpp | 2 +- .../modules/sound/src/keel/keelmodule.cpp | 42 ++- .../modules/sound/src/studio/studiomodule.cpp | 4 +- src/nostalgia/player/app.cpp | 4 +- src/olympic/applib/applib.cpp | 4 +- .../studio/applib/src/filedialogmanager.cpp | 2 +- .../studio/modlib/include/studio/editor.hpp | 2 + .../turbine/include/turbine/clipboard.hpp | 2 +- .../turbine/include/turbine/context.hpp | 9 - src/olympic/turbine/include/turbine/event.hpp | 17 - src/olympic/turbine/include/turbine/gfx.hpp | 4 +- src/olympic/turbine/include/turbine/input.hpp | 79 ----- .../turbine/include/turbine/turbine.hpp | 80 ++++- src/olympic/turbine/src/gba/CMakeLists.txt | 2 - src/olympic/turbine/src/gba/clipboard.cpp | 5 + src/olympic/turbine/src/gba/context.hpp | 3 +- src/olympic/turbine/src/gba/event.cpp | 23 -- src/olympic/turbine/src/gba/gfx.cpp | 50 --- src/olympic/turbine/src/gba/turbine.cpp | 50 ++- src/olympic/turbine/src/glfw/CMakeLists.txt | 2 - src/olympic/turbine/src/glfw/clipboard.cpp | 2 +- src/olympic/turbine/src/glfw/context.hpp | 1 - src/olympic/turbine/src/glfw/event.cpp | 23 -- src/olympic/turbine/src/glfw/gfx.cpp | 324 ------------------ src/olympic/turbine/src/glfw/turbine.cpp | 324 +++++++++++++++++- 45 files changed, 768 insertions(+), 967 deletions(-) delete mode 100644 src/nostalgia/modules/gfx/include/nostalgia/gfx/core.hpp delete mode 100644 src/nostalgia/modules/gfx/src/gba/CMakeLists.txt delete mode 100644 src/nostalgia/modules/gfx/src/gba/context.cpp delete mode 100644 src/nostalgia/modules/gfx/src/gba/context.hpp delete mode 100644 src/nostalgia/modules/gfx/src/gba/gfx.hpp delete mode 100644 src/nostalgia/modules/gfx/src/gba/panic.cpp rename src/nostalgia/modules/gfx/src/{gba/gfx.cpp => gfx-gba.cpp} (78%) rename src/nostalgia/modules/gfx/src/{opengl/gfx.cpp => gfx-opengl.cpp} (86%) delete mode 100644 src/nostalgia/modules/gfx/src/opengl/CMakeLists.txt delete mode 100644 src/nostalgia/modules/gfx/src/opengl/context.cpp delete mode 100644 src/nostalgia/modules/gfx/src/opengl/context.hpp delete mode 100644 src/nostalgia/modules/gfx/src/opengl/gfx.hpp delete mode 100644 src/olympic/turbine/include/turbine/event.hpp delete mode 100644 src/olympic/turbine/include/turbine/input.hpp delete mode 100644 src/olympic/turbine/src/gba/event.cpp delete mode 100644 src/olympic/turbine/src/gba/gfx.cpp delete mode 100644 src/olympic/turbine/src/glfw/event.cpp delete mode 100644 src/olympic/turbine/src/glfw/gfx.cpp diff --git a/deps/ox/src/ox/std/stringview.hpp b/deps/ox/src/ox/std/stringview.hpp index eef1cc4..6a2221e 100644 --- a/deps/ox/src/ox/std/stringview.hpp +++ b/deps/ox/src/ox/std/stringview.hpp @@ -60,7 +60,7 @@ class StringView: public detail::BaseStringView { }; -using StringViewCR = const StringView&; +using StringViewCR = StringView const&; constexpr auto operator==(StringViewCR s1, StringViewCR s2) noexcept { if (s2.len() != s1.len()) { @@ -89,7 +89,7 @@ constexpr auto operator<=>(StringViewCR s1, StringViewCR s2) noexcept { } } -constexpr auto write(Writer_c auto &writer, ox::StringViewCR sv) noexcept { +constexpr auto write(Writer_c auto &writer, StringViewCR sv) noexcept { return writer.write(sv.data(), sv.bytes()); } @@ -100,7 +100,7 @@ constexpr auto toStdStringView(StringViewCR sv) noexcept { #endif -constexpr ox::Result strToInt(ox::StringViewCR str) noexcept { +constexpr ox::Result strToInt(StringViewCR str) noexcept { OX_ALLOW_UNSAFE_BUFFERS_BEGIN int total = 0; int multiplier = 1; diff --git a/src/nostalgia/modules/gfx/include/nostalgia/gfx/core.hpp b/src/nostalgia/modules/gfx/include/nostalgia/gfx/core.hpp deleted file mode 100644 index e34c58a..0000000 --- a/src/nostalgia/modules/gfx/include/nostalgia/gfx/core.hpp +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved. - */ - -#pragma once - -#include "color.hpp" -#include "context.hpp" -#include "gfx.hpp" -#include "initparams.hpp" -#include "keelmodule.hpp" -#include "palette.hpp" -#include "ptidxconv.hpp" -#include "tilesheet.hpp" diff --git a/src/nostalgia/modules/gfx/include/nostalgia/gfx/gfx.hpp b/src/nostalgia/modules/gfx/include/nostalgia/gfx/gfx.hpp index 3736d23..8f265d8 100644 --- a/src/nostalgia/modules/gfx/include/nostalgia/gfx/gfx.hpp +++ b/src/nostalgia/modules/gfx/include/nostalgia/gfx/gfx.hpp @@ -9,8 +9,12 @@ #include #include +#include "color.hpp" #include "context.hpp" +#include "initparams.hpp" +#include "keelmodule.hpp" #include "palette.hpp" +#include "ptidxconv.hpp" #include "tilesheet.hpp" namespace nostalgia::gfx { diff --git a/src/nostalgia/modules/gfx/include/nostalgia/gfx/keelmodule.hpp b/src/nostalgia/modules/gfx/include/nostalgia/gfx/keelmodule.hpp index da976b3..3258f94 100644 --- a/src/nostalgia/modules/gfx/include/nostalgia/gfx/keelmodule.hpp +++ b/src/nostalgia/modules/gfx/include/nostalgia/gfx/keelmodule.hpp @@ -8,6 +8,6 @@ namespace nostalgia::gfx { -const keel::Module *keelModule() noexcept; +keel::Module const *keelModule() noexcept; } diff --git a/src/nostalgia/modules/gfx/include/nostalgia/gfx/studiomodule.hpp b/src/nostalgia/modules/gfx/include/nostalgia/gfx/studiomodule.hpp index c950021..024d07e 100644 --- a/src/nostalgia/modules/gfx/include/nostalgia/gfx/studiomodule.hpp +++ b/src/nostalgia/modules/gfx/include/nostalgia/gfx/studiomodule.hpp @@ -8,6 +8,6 @@ namespace nostalgia::gfx { -const studio::Module *studioModule() noexcept; +studio::Module const *studioModule() noexcept; } diff --git a/src/nostalgia/modules/gfx/src/CMakeLists.txt b/src/nostalgia/modules/gfx/src/CMakeLists.txt index 20630a7..7c8bb5e 100644 --- a/src/nostalgia/modules/gfx/src/CMakeLists.txt +++ b/src/nostalgia/modules/gfx/src/CMakeLists.txt @@ -4,11 +4,6 @@ add_library( tilesheet.cpp ) -add_subdirectory(gba) -if(NOT BUILDCORE_TARGET STREQUAL "gba") - add_subdirectory(opengl) -endif() - target_include_directories( NostalgiaGfx PUBLIC ../include @@ -31,3 +26,38 @@ install( LIBRARY DESTINATION lib ARCHIVE DESTINATION lib ) + +# OpenGL + +if(NOT BUILDCORE_TARGET STREQUAL "gba") + target_sources( + NostalgiaGfx PRIVATE + gfx-opengl.cpp + ) + target_link_libraries( + NostalgiaGfx PUBLIC + GlUtils + ) +endif() + +# GBA + +add_library( + NostalgiaGfx-GBA OBJECT + gfx-gba.cpp +) +target_include_directories( + NostalgiaGfx-GBA PUBLIC + ../include +) +target_link_libraries( + NostalgiaGfx-GBA PUBLIC + TeaGBA + Keel + Turbine +) + +if(BUILDCORE_TARGET STREQUAL "gba") + set_source_files_properties(gfx-gba.cpp PROPERTIES COMPILE_FLAGS -marm) + target_link_libraries(NostalgiaGfx PUBLIC NostalgiaGfx-GBA) +endif() diff --git a/src/nostalgia/modules/gfx/src/gba/CMakeLists.txt b/src/nostalgia/modules/gfx/src/gba/CMakeLists.txt deleted file mode 100644 index 24c64c5..0000000 --- a/src/nostalgia/modules/gfx/src/gba/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -add_library( - NostalgiaGfx-GBA OBJECT - context.cpp - gfx.cpp - panic.cpp -) -target_include_directories( - NostalgiaGfx-GBA PUBLIC - ../../include -) -target_link_libraries( - NostalgiaGfx-GBA PUBLIC - TeaGBA - Keel - Turbine -) - -if(BUILDCORE_TARGET STREQUAL "gba") - set_source_files_properties(gfx.cpp PROPERTIES COMPILE_FLAGS -marm) - target_link_libraries(NostalgiaGfx PUBLIC NostalgiaGfx-GBA) -endif() diff --git a/src/nostalgia/modules/gfx/src/gba/context.cpp b/src/nostalgia/modules/gfx/src/gba/context.cpp deleted file mode 100644 index d3a358d..0000000 --- a/src/nostalgia/modules/gfx/src/gba/context.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved. - */ - -#include - -#include - -#include "context.hpp" - -namespace nostalgia::gfx { - -void safeDelete(Context *ctx) noexcept { - delete ctx; -} - -Context::Context(turbine::Context &tctx) noexcept: turbineCtx(tctx) { -} - -ox::Error initGfx(Context &ctx, InitParams const&) noexcept; - -ox::Result> init(turbine::Context &tctx, InitParams const¶ms) noexcept { - auto ctx = ox::make_unique(tctx); - OX_RETURN_ERROR(initGfx(*ctx, params)); - return ctx; -} - -keel::Context &keelCtx(Context &ctx) noexcept { - return turbine::keelCtx(ctx.turbineCtx); -} - -turbine::Context &turbineCtx(Context &ctx) noexcept { - return ctx.turbineCtx; -} - -} diff --git a/src/nostalgia/modules/gfx/src/gba/context.hpp b/src/nostalgia/modules/gfx/src/gba/context.hpp deleted file mode 100644 index c748d2d..0000000 --- a/src/nostalgia/modules/gfx/src/gba/context.hpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved. - */ - -#pragma once - -#include - -namespace nostalgia::gfx { - -struct BgCbbData { - unsigned bpp = 4; -}; - -class Context { - - public: - turbine::Context &turbineCtx; - ox::Array cbbData; - - explicit Context(turbine::Context &tctx) noexcept; - Context(Context &other) noexcept = delete; - Context(Context const&other) noexcept = delete; - Context(Context const&&other) noexcept = delete; - virtual ~Context() noexcept = default; - - [[nodiscard]] - ox::MemFS const&rom() const noexcept { - return static_cast(*turbine::rom(turbineCtx)); - } - -}; - -} \ No newline at end of file diff --git a/src/nostalgia/modules/gfx/src/gba/gfx.hpp b/src/nostalgia/modules/gfx/src/gba/gfx.hpp deleted file mode 100644 index ea7aee7..0000000 --- a/src/nostalgia/modules/gfx/src/gba/gfx.hpp +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved. - */ - -#pragma once - -#include - -namespace nostalgia::gfx { -ox::Error initGfx(Context &ctx, InitParams const&) noexcept; -} diff --git a/src/nostalgia/modules/gfx/src/gba/panic.cpp b/src/nostalgia/modules/gfx/src/gba/panic.cpp deleted file mode 100644 index 1b886e2..0000000 --- a/src/nostalgia/modules/gfx/src/gba/panic.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved. - */ - - -#include -#include - -#include -#include - -#include -#include - -#include - -#include "gfx.hpp" - -#define HEAP_BEGIN (reinterpret_cast(MEM_EWRAM_BEGIN)) -#define HEAP_SIZE ((MEM_EWRAM_END - MEM_EWRAM_BEGIN) / 2) -#define HEAP_END (reinterpret_cast(MEM_EWRAM_BEGIN + HEAP_SIZE)) - -namespace ox { - -using namespace nostalgia::gfx; - -void panic(const char *file, int line, const char *panicMsg, ox::Error const&err) noexcept { - // reset heap to make sure we have enough memory to allocate context data -OX_ALLOW_UNSAFE_BUFFERS_BEGIN - ox::heapmgr::initHeap(HEAP_BEGIN, HEAP_END); -OX_ALLOW_UNSAFE_BUFFERS_END - auto tctx = turbine::init(keel::loadRomFs("").unwrap(), "Nostalgia").unwrap(); - auto ctx = init(*tctx).unwrap(); - std::ignore = initGfx(*ctx, {}); - std::ignore = initConsole(*ctx); - setBgStatus(*ctx, 0, true); - clearBg(*ctx, 0); - auto const serr = ox::sfmt>("Error code: {}", static_cast(err)); - consoleWrite(*ctx, 32 + 1, 1, "SADNESS..."); - consoleWrite(*ctx, 32 + 1, 4, "UNEXPECTED STATE:"); - consoleWrite(*ctx, 32 + 2, 6, panicMsg); - if (err) { - consoleWrite(*ctx, 32 + 2, 8, serr); - } - consoleWrite(*ctx, 32 + 1, 15, "PLEASE RESTART THE SYSTEM"); - // print to terminal if in mGBA - oxErrf("\033[31;1;1mPANIC:\033[0m [{}:{}]: {}\n", file, line, panicMsg); - if (err.msg) { - oxErrf("\tError Message:\t{}\n", err.msg); - } - oxErrf("\tError Code:\t{}\n", static_cast(err)); - if (err.src.file_name() != nullptr) { - oxErrf("\tError Location:\t{}:{}\n", err.src.file_name(), err.src.line()); - } - abort(); -} - -} diff --git a/src/nostalgia/modules/gfx/src/gba/gfx.cpp b/src/nostalgia/modules/gfx/src/gfx-gba.cpp similarity index 78% rename from src/nostalgia/modules/gfx/src/gba/gfx.cpp rename to src/nostalgia/modules/gfx/src/gfx-gba.cpp index e9f33f9..169933d 100644 --- a/src/nostalgia/modules/gfx/src/gba/gfx.cpp +++ b/src/nostalgia/modules/gfx/src/gfx-gba.cpp @@ -15,15 +15,48 @@ #include #include -#include "context.hpp" - OX_ALLOW_UNSAFE_BUFFERS_BEGIN namespace nostalgia::gfx { +struct BgCbbData { + unsigned bpp = 4; +}; + +class Context { + + public: + turbine::Context &turbineCtx; + ox::Array cbbData; + + explicit Context(turbine::Context &tctx) noexcept: turbineCtx{tctx} {} + Context(Context &other) noexcept = delete; + Context(Context const&other) noexcept = delete; + Context(Context const&&other) noexcept = delete; + virtual ~Context() noexcept = default; + + [[nodiscard]] + ox::MemFS const&rom() const noexcept { + return static_cast(*turbine::rom(turbineCtx)); + } + +}; + +void safeDelete(Context *ctx) noexcept { + delete ctx; +} + +keel::Context &keelCtx(Context &ctx) noexcept { + return turbine::keelCtx(ctx.turbineCtx); +} + +turbine::Context &turbineCtx(Context &ctx) noexcept { + return ctx.turbineCtx; +} + static constexpr auto SpriteCount = 128; -ox::Error initGfx(Context&, InitParams const&) noexcept { +static ox::Error initGfx() noexcept { for (auto bgCtl = ®_BG0CTL; bgCtl <= ®_BG3CTL; bgCtl += 2) { teagba::bgSetSbb(*bgCtl, 28); } @@ -34,6 +67,12 @@ ox::Error initGfx(Context&, InitParams const&) noexcept { return {}; } +ox::Result> init(turbine::Context &tctx, InitParams const&) noexcept { + auto ctx = ox::make_unique(tctx); + OX_RETURN_ERROR(initGfx()); + return ctx; +} + ox::Error loadBgPalette( Context&, size_t const palBank, @@ -300,4 +339,43 @@ uint_t spriteCount(Context const&) noexcept { } +namespace ox { + +void panic(const char *file, int line, const char *panicMsg, ox::Error const&err) noexcept { + using namespace nostalgia::gfx; + // reset heap to make sure we have enough memory to allocate context data + OX_ALLOW_UNSAFE_BUFFERS_BEGIN + const auto heapBegin = reinterpret_cast(MEM_EWRAM_BEGIN); + const auto heapSz = (MEM_EWRAM_END - MEM_EWRAM_BEGIN) / 2; + const auto heapEnd = reinterpret_cast(MEM_EWRAM_BEGIN + heapSz); + ox::heapmgr::initHeap(heapBegin, heapEnd); + OX_ALLOW_UNSAFE_BUFFERS_END + auto tctx = turbine::init(keel::loadRomFs("").unwrap(), "Nostalgia").unwrap(); + auto ctx = init(*tctx).unwrap(); + std::ignore = initGfx(); + std::ignore = initConsole(*ctx); + setBgStatus(*ctx, 0, true); + clearBg(*ctx, 0); + auto const serr = ox::sfmt>("Error code: {}", static_cast(err)); + consoleWrite(*ctx, 32 + 1, 1, "SADNESS..."); + consoleWrite(*ctx, 32 + 1, 4, "UNEXPECTED STATE:"); + consoleWrite(*ctx, 32 + 2, 6, panicMsg); + if (err) { + consoleWrite(*ctx, 32 + 2, 8, serr); + } + consoleWrite(*ctx, 32 + 1, 15, "PLEASE RESTART THE SYSTEM"); + // print to terminal if in mGBA + oxErrf("\033[31;1;1mPANIC:\033[0m [{}:{}]: {}\n", file, line, panicMsg); + if (err.msg) { + oxErrf("\tError Message:\t{}\n", err.msg); + } + oxErrf("\tError Code:\t{}\n", static_cast(err)); + if (err.src.file_name() != nullptr) { + oxErrf("\tError Location:\t{}:{}\n", err.src.file_name(), err.src.line()); + } + abort(); +} + +} + OX_ALLOW_UNSAFE_BUFFERS_END diff --git a/src/nostalgia/modules/gfx/src/opengl/gfx.cpp b/src/nostalgia/modules/gfx/src/gfx-opengl.cpp similarity index 86% rename from src/nostalgia/modules/gfx/src/opengl/gfx.cpp rename to src/nostalgia/modules/gfx/src/gfx-opengl.cpp index efbe686..182d09b 100644 --- a/src/nostalgia/modules/gfx/src/opengl/gfx.cpp +++ b/src/nostalgia/modules/gfx/src/gfx-opengl.cpp @@ -4,7 +4,6 @@ #include #include -#include #include @@ -15,22 +14,105 @@ #include #include -#include "context.hpp" -#include "gfx.hpp" - namespace nostalgia::gfx { +namespace renderer { + +constexpr uint64_t TileRows = 128; +constexpr uint64_t TileColumns = 128; +constexpr uint64_t TileCount = TileRows * TileColumns; +constexpr uint64_t BgVertexVboRows = 4; +constexpr uint64_t BgVertexVboRowLength = 7; +constexpr uint64_t BgVertexVboLength = BgVertexVboRows * BgVertexVboRowLength; +constexpr uint64_t BgVertexEboLength = 6; +constexpr uint64_t SpriteVertexVboRows = 4; +constexpr uint64_t SpriteVertexVboRowLength = 6; +constexpr uint64_t SpriteVertexVboLength = SpriteVertexVboRows * SpriteVertexVboRowLength; +constexpr uint64_t SpriteVertexEboLength = 6; + +struct CBB: glutils::BufferSet { + bool updated = false; + ox::Array pixels; + constexpr CBB() noexcept { + vertices.resize(TileCount * BgVertexVboLength); + elements.resize(TileCount * BgVertexEboLength); + } +}; + +struct SpriteBlockset: glutils::BufferSet { + bool updated = false; + constexpr SpriteBlockset(uint64_t spriteCount, uint64_t blocksPerSprite) noexcept { + vertices.resize(spriteCount * SpriteVertexVboLength * blocksPerSprite); + elements.resize(spriteCount * SpriteVertexEboLength * blocksPerSprite); + } +}; + +struct Background { + float priority = 0; + bool enabled = false; + unsigned cbbIdx = 0; +}; + +} + +class Context { + public: + class Drawer final: public turbine::gl::Drawer { + private: + Context &m_ctx; + public: + explicit Drawer(Context &ctx) noexcept: m_ctx{ctx} {} + void draw(turbine::Context &tctx) noexcept override { + gl::draw(m_ctx, turbine::getScreenSize(tctx)); + } + }; + + turbine::Context &turbineCtx; + glutils::GLProgram bgShader; + glutils::GLProgram spriteShader; + ox::Array cbbs; + renderer::SpriteBlockset spriteBlocks; + ox::Array spriteStates; + ox::Array bgPalette; + ox::Array backgrounds; + Drawer drawer; + uint_t spriteCount = 0; + uint_t blocksPerSprite = 0; + + explicit Context(turbine::Context &tctx, InitParams const ¶ms) noexcept: + turbineCtx{tctx}, + spriteBlocks{params.glSpriteCount, params.glBlocksPerSprite}, + drawer{*this}, + spriteCount{params.glSpriteCount}, + blocksPerSprite{params.glBlocksPerSprite} { + } + Context(Context const&) = delete; + Context(Context&&) = delete; + Context &operator=(Context const&) = delete; + Context &operator=(Context&&) = delete; + ~Context() noexcept { + turbine::gl::removeDrawer(turbineCtx, &drawer); + } +}; + +void safeDelete(Context *ctx) noexcept { + delete ctx; +} + +keel::Context &keelCtx(Context &ctx) noexcept { + return turbine::keelCtx(ctx.turbineCtx); +} + +turbine::Context &turbineCtx(Context &ctx) noexcept { + return ctx.turbineCtx; +} + + namespace renderer { static constexpr auto Scale = 1; static constexpr auto PriorityScale = 0.01f; -Drawer::Drawer(Context &ctx) noexcept: m_ctx(ctx) {} - -void Drawer::draw(turbine::Context &tctx) noexcept { - gl::draw(m_ctx, turbine::getScreenSize(tctx)); -} - static constexpr ox::CStringView bgvshadTmpl = R"glsl( {} in vec2 vTexCoord; @@ -241,7 +323,13 @@ static void initSpritesBufferset(Context &ctx) noexcept { // in float vEnabled; auto const enabledAttr = static_cast(glGetAttribLocation(shader, "vEnabled")); glEnableVertexAttribArray(enabledAttr); - glVertexAttribPointer(enabledAttr, 1, GL_FLOAT, GL_FALSE, SpriteVertexVboRowLength * sizeof(float), nullptr); + glVertexAttribPointer( + enabledAttr, + 1, + GL_FLOAT, + GL_FALSE, + SpriteVertexVboRowLength * sizeof(float), + nullptr); // in vec3 vPosition; auto const posAttr = static_cast(glGetAttribLocation(shader, "vPosition")); glEnableVertexAttribArray(posAttr); @@ -250,8 +338,9 @@ static void initSpritesBufferset(Context &ctx) noexcept { // in vec2 vTexCoord; auto const texCoordAttr = static_cast(glGetAttribLocation(shader, "vTexCoord")); glEnableVertexAttribArray(texCoordAttr); - glVertexAttribPointer(texCoordAttr, 2, GL_FLOAT, GL_FALSE, SpriteVertexVboRowLength * sizeof(float), - std::bit_cast(uintptr_t{4 * sizeof(float)})); + glVertexAttribPointer( + texCoordAttr, 2, GL_FLOAT, GL_FALSE, SpriteVertexVboRowLength * sizeof(float), + std::bit_cast(uintptr_t{4 * sizeof(float)})); glBindVertexArray(0); } @@ -270,7 +359,13 @@ static void initBackgroundBufferset( // vbo layout auto const posAttr = static_cast(glGetAttribLocation(shader, "vPosition")); glEnableVertexAttribArray(posAttr); - glVertexAttribPointer(posAttr, 3, GL_FLOAT, GL_FALSE, BgVertexVboRowLength * sizeof(float), nullptr); + glVertexAttribPointer( + posAttr, + 3, + GL_FLOAT, + GL_FALSE, + BgVertexVboRowLength * sizeof(float), + nullptr); auto const texCoordAttr = static_cast(glGetAttribLocation(shader, "vTexCoord")); glEnableVertexAttribArray(texCoordAttr); glVertexAttribPointer( @@ -300,7 +395,16 @@ static glutils::GLTexture createTexture( tex.height = h; glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, tex.id); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width, tex.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_RGBA, + tex.width, + tex.height, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + pixels); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -470,28 +574,23 @@ static void setSprite( } -ox::Error initGfx( - Context &ctx, - InitParams const&initParams) noexcept { +ox::Result> init(turbine::Context &tctx, InitParams const¶ms) noexcept { + auto ctx = ox::make_unique(tctx, params); const auto bgVshad = ox::sfmt(renderer::bgvshadTmpl, gl::GlslVersion); const auto bgFshad = ox::sfmt(renderer::bgfshadTmpl, gl::GlslVersion); const auto spriteVshad = ox::sfmt(renderer::spritevshadTmpl, gl::GlslVersion); const auto spriteFshad = ox::sfmt(renderer::spritefshadTmpl, gl::GlslVersion); - OX_RETURN_ERROR(glutils::buildShaderProgram(bgVshad, bgFshad).moveTo(ctx.bgShader)); + OX_RETURN_ERROR(glutils::buildShaderProgram(bgVshad, bgFshad).moveTo(ctx->bgShader)); OX_RETURN_ERROR( - glutils::buildShaderProgram(spriteVshad, spriteFshad).moveTo(ctx.spriteShader)); - for (auto &cbb : ctx.cbbs) { - initBackgroundBufferset(ctx.bgShader, cbb); + glutils::buildShaderProgram(spriteVshad, spriteFshad).moveTo(ctx->spriteShader)); + for (auto &cbb : ctx->cbbs) { + initBackgroundBufferset(ctx->bgShader, cbb); } - renderer::initSpritesBufferset(ctx); - if (initParams.glInstallDrawer) { - turbine::gl::addDrawer(ctx.turbineCtx, &ctx.drawer); + renderer::initSpritesBufferset(*ctx); + if (params.glInstallDrawer) { + turbine::gl::addDrawer(ctx->turbineCtx, &ctx->drawer); } - return {}; -} - -void shutdownGfx(Context &ctx) noexcept { - turbine::gl::removeDrawer(ctx.turbineCtx, &ctx.drawer); + return ctx; } struct TileSheetData { diff --git a/src/nostalgia/modules/gfx/src/gfx.cpp b/src/nostalgia/modules/gfx/src/gfx.cpp index cc3d97e..89f0968 100644 --- a/src/nostalgia/modules/gfx/src/gfx.cpp +++ b/src/nostalgia/modules/gfx/src/gfx.cpp @@ -20,7 +20,7 @@ int tileRows(Context&) noexcept { ox::Error loadBgPalette( Context &ctx, - size_t palBank, + size_t const palBank, ox::StringViewCR palettePath) noexcept { OX_REQUIRE(pal, keel::readObj(keelCtx(ctx), palettePath)); return loadBgPalette(ctx, palBank, *pal, 0); @@ -28,8 +28,8 @@ ox::Error loadBgPalette( ox::Error loadBgPalette( Context &ctx, - size_t palBank, - ox::FileAddress const&paletteAddr) noexcept { + size_t const palBank, + ox::FileAddress const &paletteAddr) noexcept { OX_REQUIRE(pal, keel::readObj(keelCtx(ctx), paletteAddr)); return loadBgPalette(ctx, palBank, *pal, 0); } @@ -43,18 +43,18 @@ ox::Error loadSpritePalette( ox::Error loadSpritePalette( Context &ctx, - ox::FileAddress const&paletteAddr) noexcept { + ox::FileAddress const &paletteAddr) noexcept { OX_REQUIRE(pal, keel::readObj(keelCtx(ctx), paletteAddr)); return loadSpritePalette(ctx, *pal, 0); } ox::Error loadBgTileSheet( Context &ctx, - unsigned cbb, + unsigned const cbb, ox::FileAddress const&tsAddr, - size_t dstTileIdx, - size_t srcTileIdx, - size_t tileCnt) noexcept { + size_t const dstTileIdx, + size_t const srcTileIdx, + size_t const tileCnt) noexcept { OX_REQUIRE(ts, keel::readObj(keelCtx(ctx), tsAddr)); return loadBgTileSheet(ctx, cbb, *ts, dstTileIdx, srcTileIdx, tileCnt); } @@ -63,16 +63,16 @@ ox::Error loadBgTileSheet( Context &ctx, unsigned cbb, ox::StringViewCR tsPath, - size_t dstTileIdx, - size_t srcTileIdx, - size_t tileCnt) noexcept { + size_t const dstTileIdx, + size_t const srcTileIdx, + size_t const tileCnt) noexcept { OX_REQUIRE(ts, keel::readObj(keelCtx(ctx), tsPath)); return loadBgTileSheet(ctx, cbb, *ts, dstTileIdx, srcTileIdx, tileCnt); } ox::Error loadBgTileSheet( Context &ctx, - unsigned cbb, + unsigned const cbb, ox::StringViewCR tilesheetPath, ox::Optional const&paletteBank) noexcept { OX_REQUIRE(ts, keel::readObj(keelCtx(ctx), tilesheetPath)); @@ -81,7 +81,7 @@ ox::Error loadBgTileSheet( ox::Error loadBgTileSheet( Context &ctx, - unsigned cbb, + unsigned const cbb, ox::FileAddress const&tilesheetAddr, ox::Optional const&paletteBank) noexcept { OX_REQUIRE(ts, keel::readObj(keelCtx(ctx), tilesheetAddr)); @@ -91,7 +91,7 @@ ox::Error loadBgTileSheet( ox::Error loadSpriteTileSheet( Context &ctx, ox::StringViewCR tilesheetPath, - bool loadDefaultPalette) noexcept { + bool const loadDefaultPalette) noexcept { OX_REQUIRE(ts, readObj(keelCtx(ctx), tilesheetPath)); return loadSpriteTileSheet(ctx, *ts, loadDefaultPalette); } @@ -99,7 +99,7 @@ ox::Error loadSpriteTileSheet( ox::Error loadSpriteTileSheet( Context &ctx, ox::FileAddress const&tilesheetAddr, - bool loadDefaultPalette) noexcept { + bool const loadDefaultPalette) noexcept { OX_REQUIRE(ts, readObj(keelCtx(ctx), tilesheetAddr)); return loadSpriteTileSheet(ctx, *ts, loadDefaultPalette); } @@ -235,7 +235,13 @@ constexpr ox::Array charMap = { 50, // ~ }; -void setBgTile(Context &ctx, uint_t bgIdx, int column, int row, unsigned tile, unsigned palBank) noexcept { +void setBgTile( + Context &ctx, + uint_t const bgIdx, + int const column, + int const row, + unsigned const tile, + unsigned const palBank) noexcept { setBgTile(ctx, bgIdx, column, row, { .tileIdx = tile, .palBank = palBank, diff --git a/src/nostalgia/modules/gfx/src/opengl/CMakeLists.txt b/src/nostalgia/modules/gfx/src/opengl/CMakeLists.txt deleted file mode 100644 index f3a72af..0000000 --- a/src/nostalgia/modules/gfx/src/opengl/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -target_sources( - NostalgiaGfx PRIVATE - context.cpp - gfx.cpp -) -target_link_libraries( - NostalgiaGfx PUBLIC - GlUtils -) diff --git a/src/nostalgia/modules/gfx/src/opengl/context.cpp b/src/nostalgia/modules/gfx/src/opengl/context.cpp deleted file mode 100644 index 3bb6486..0000000 --- a/src/nostalgia/modules/gfx/src/opengl/context.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved. - */ - -#include "context.hpp" -#include "gfx.hpp" - -namespace nostalgia::gfx { - -void safeDelete(Context *ctx) noexcept { - delete ctx; -} - -Context::Context(turbine::Context &tctx, InitParams const¶ms) noexcept: - turbineCtx(tctx), - spriteBlocks(params.glSpriteCount, params.glBlocksPerSprite), - drawer(*this), - spriteCount(params.glSpriteCount), - blocksPerSprite(params.glBlocksPerSprite) { -} - -Context::~Context() noexcept { - shutdownGfx(*this); -} - -ox::Result> init(turbine::Context &tctx, InitParams const¶ms) noexcept { - auto ctx = ox::make_unique(tctx, params); - OX_RETURN_ERROR(initGfx(*ctx, params)); - return ctx; -} - -keel::Context &keelCtx(Context &ctx) noexcept { - return turbine::keelCtx(ctx.turbineCtx); -} - -turbine::Context &turbineCtx(Context &ctx) noexcept { - return ctx.turbineCtx; -} - -} diff --git a/src/nostalgia/modules/gfx/src/opengl/context.hpp b/src/nostalgia/modules/gfx/src/opengl/context.hpp deleted file mode 100644 index be93bf0..0000000 --- a/src/nostalgia/modules/gfx/src/opengl/context.hpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved. - */ - -#pragma once - -#include - -#include - -#include -#include - -#include "gfx.hpp" - -namespace nostalgia::gfx { - -class Context { - - public: - turbine::Context &turbineCtx; - glutils::GLProgram bgShader; - glutils::GLProgram spriteShader; - ox::Array cbbs; - renderer::SpriteBlockset spriteBlocks; - ox::Array spriteStates; - ox::Array bgPalette; - ox::Array backgrounds; - renderer::Drawer drawer; - uint_t spriteCount = 0; - uint_t blocksPerSprite = 0; - explicit Context(turbine::Context &tctx, InitParams const¶ms) noexcept; - Context(Context const&) = delete; - Context(Context&&) = delete; - Context &operator=(Context const&) = delete; - Context &operator=(Context&&) = delete; - ~Context() noexcept; -}; - -} diff --git a/src/nostalgia/modules/gfx/src/opengl/gfx.hpp b/src/nostalgia/modules/gfx/src/opengl/gfx.hpp deleted file mode 100644 index b852a2c..0000000 --- a/src/nostalgia/modules/gfx/src/opengl/gfx.hpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved. - */ - -#pragma once - -#include - -#include - -#include - -#include - -namespace nostalgia::gfx::renderer { - -constexpr uint64_t TileRows = 128; -constexpr uint64_t TileColumns = 128; -constexpr uint64_t TileCount = TileRows * TileColumns; -constexpr uint64_t BgVertexVboRows = 4; -constexpr uint64_t BgVertexVboRowLength = 7; -constexpr uint64_t BgVertexVboLength = BgVertexVboRows * BgVertexVboRowLength; -constexpr uint64_t BgVertexEboLength = 6; -constexpr uint64_t SpriteVertexVboRows = 4; -constexpr uint64_t SpriteVertexVboRowLength = 6; -constexpr uint64_t SpriteVertexVboLength = SpriteVertexVboRows * SpriteVertexVboRowLength; -constexpr uint64_t SpriteVertexEboLength = 6; - -struct CBB: public glutils::BufferSet { - bool updated = false; - ox::Array pixels; - constexpr CBB() noexcept { - vertices.resize(TileCount * BgVertexVboLength); - elements.resize(TileCount * BgVertexEboLength); - } -}; - -struct SpriteBlockset: public glutils::BufferSet { - bool updated = false; - constexpr SpriteBlockset(uint64_t spriteCount, uint64_t blocksPerSprite) noexcept { - vertices.resize(spriteCount * SpriteVertexVboLength * blocksPerSprite); - elements.resize(spriteCount * SpriteVertexEboLength * blocksPerSprite); - } -}; - -struct Background { - float priority = 0; - bool enabled = false; - unsigned cbbIdx = 0; -}; - -class Drawer: public turbine::gl::Drawer { - private: - Context &m_ctx; - public: - explicit Drawer(Context &ctx) noexcept; - void draw(turbine::Context&) noexcept final; -}; - -} - -namespace nostalgia::gfx { -ox::Error initGfx(Context &ctx, InitParams const&) noexcept; -void shutdownGfx(Context &ctx) noexcept; -} diff --git a/src/nostalgia/modules/gfx/test/tests.cpp b/src/nostalgia/modules/gfx/test/tests.cpp index 21476b3..ed74593 100644 --- a/src/nostalgia/modules/gfx/test/tests.cpp +++ b/src/nostalgia/modules/gfx/test/tests.cpp @@ -6,16 +6,16 @@ #include #include -#include -#include +#include +#include using namespace nostalgia; static std::map tests = { { "readWriteTileSheet", - []() -> ox::Error { - gfx::TileSheet in; + [] -> ox::Error { + gfx::TileSheet const in; OX_REQUIRE(buff, ox::writeMC(in)); OX_REQUIRE(out, ox::readMC(buff)); oxAssert(in.subsheet.name == out.subsheet.name, "subsheet.name serialization broken"); @@ -29,7 +29,7 @@ int main(int argc, const char **argv) { if (argc > 0) { auto const args = ox::Span{argv, static_cast(argc)}; auto const testName = ox::StringView(args[1]); - if (tests.find(testName) != tests.end()) { + if (tests.contains(testName)) { retval = static_cast(tests[testName]()); } else { retval = 1; diff --git a/src/nostalgia/modules/sound/include/nostalgia/sound/keelmodule.hpp b/src/nostalgia/modules/sound/include/nostalgia/sound/keelmodule.hpp index 197e1f3..22dd532 100644 --- a/src/nostalgia/modules/sound/include/nostalgia/sound/keelmodule.hpp +++ b/src/nostalgia/modules/sound/include/nostalgia/sound/keelmodule.hpp @@ -8,6 +8,6 @@ namespace nostalgia::sound { -const keel::Module *keelModule() noexcept; +keel::Module const *keelModule() noexcept; } diff --git a/src/nostalgia/modules/sound/include/nostalgia/sound/studiomodule.hpp b/src/nostalgia/modules/sound/include/nostalgia/sound/studiomodule.hpp index f7e68e1..c807372 100644 --- a/src/nostalgia/modules/sound/include/nostalgia/sound/studiomodule.hpp +++ b/src/nostalgia/modules/sound/include/nostalgia/sound/studiomodule.hpp @@ -8,6 +8,6 @@ namespace nostalgia::sound { -const studio::Module *studioModule() noexcept; +studio::Module const *studioModule() noexcept; } diff --git a/src/nostalgia/modules/sound/src/keel/keelmodule.cpp b/src/nostalgia/modules/sound/src/keel/keelmodule.cpp index c703ec6..bd663c8 100644 --- a/src/nostalgia/modules/sound/src/keel/keelmodule.cpp +++ b/src/nostalgia/modules/sound/src/keel/keelmodule.cpp @@ -10,32 +10,30 @@ namespace nostalgia::sound { -static class: public keel::Module { - private: +static struct: keel::Module { - public: - [[nodiscard]] - ox::String id() const noexcept override { - return ox::String{"net.drinkingtea.nostalgia.sound"}; - } + [[nodiscard]] + ox::String id() const noexcept override { + return ox::String{"net.drinkingtea.nostalgia.sound"}; + } - [[nodiscard]] - ox::Vector types() const noexcept final { - return { - }; - } + [[nodiscard]] + ox::Vector types() const noexcept final { + return { + }; + } - [[nodiscard]] - ox::Vector converters() const noexcept final { - return { - }; - } + [[nodiscard]] + ox::Vector converters() const noexcept final { + return { + }; + } - [[nodiscard]] - ox::Vector packTransforms() const noexcept final { - return { - }; - } + [[nodiscard]] + ox::Vector packTransforms() const noexcept final { + return { + }; + } } const mod; diff --git a/src/nostalgia/modules/sound/src/studio/studiomodule.cpp b/src/nostalgia/modules/sound/src/studio/studiomodule.cpp index 0a2369d..0806dfe 100644 --- a/src/nostalgia/modules/sound/src/studio/studiomodule.cpp +++ b/src/nostalgia/modules/sound/src/studio/studiomodule.cpp @@ -8,7 +8,8 @@ namespace nostalgia::sound { -static class: public studio::Module { +static struct: studio::Module { + ox::Vector editors(studio::Context&) const noexcept final { return { }; @@ -18,6 +19,7 @@ static class: public studio::Module { ox::Vector> out; return out; } + } const mod; const studio::Module *studioModule() noexcept { diff --git a/src/nostalgia/player/app.cpp b/src/nostalgia/player/app.cpp index 7caef45..aeddbed 100644 --- a/src/nostalgia/player/app.cpp +++ b/src/nostalgia/player/app.cpp @@ -5,7 +5,7 @@ #include #include -#include +#include using namespace nostalgia; @@ -52,7 +52,7 @@ static int testUpdateHandler(turbine::Context &tctx) noexcept { } [[maybe_unused]] -static void testKeyEventHandler(turbine::Context &tctx, turbine::Key key, bool down) noexcept { +static void testKeyEventHandler(turbine::Context &tctx, turbine::Key const key, bool const down) noexcept { if (down) { if (key == turbine::Key::Alpha_Q) { turbine::requestShutdown(tctx); diff --git a/src/olympic/applib/applib.cpp b/src/olympic/applib/applib.cpp index ac1a7e8..270903b 100644 --- a/src/olympic/applib/applib.cpp +++ b/src/olympic/applib/applib.cpp @@ -38,7 +38,7 @@ #endif namespace olympic { -ox::String appVersion = ox::String(OLYMPIC_APP_VERSION); +ox::String appVersion{OLYMPIC_APP_VERSION}; } ox::Error run( @@ -57,7 +57,7 @@ int WinMain() { auto const argc = __argc; auto const argv = const_cast(__argv); #else -int main(int argc, char const**argv) { +int main(int const argc, char const **argv) { #endif OX_INIT_DEBUG_LOGGER(loggerConn, OLYMPIC_PROJECT_NAME " " OLYMPIC_APP_NAME) #if OLYMPIC_LOAD_KEEL_MODULES diff --git a/src/olympic/studio/applib/src/filedialogmanager.cpp b/src/olympic/studio/applib/src/filedialogmanager.cpp index bb4c941..f447717 100644 --- a/src/olympic/studio/applib/src/filedialogmanager.cpp +++ b/src/olympic/studio/applib/src/filedialogmanager.cpp @@ -8,7 +8,7 @@ namespace studio { -studio::TaskState FileDialogManager::update(turbine::Context &ctx) noexcept { +TaskState FileDialogManager::update(turbine::Context &ctx) noexcept { switch (m_state) { case UpdateProjectPathState::EnableSystemCursor: { // switch to system cursor in this update and open file dialog in the next diff --git a/src/olympic/studio/modlib/include/studio/editor.hpp b/src/olympic/studio/modlib/include/studio/editor.hpp index 6b68b24..341fa2f 100644 --- a/src/olympic/studio/modlib/include/studio/editor.hpp +++ b/src/olympic/studio/modlib/include/studio/editor.hpp @@ -6,6 +6,8 @@ #include +#include + #include "undostack.hpp" #include "widget.hpp" diff --git a/src/olympic/turbine/include/turbine/clipboard.hpp b/src/olympic/turbine/include/turbine/clipboard.hpp index ffd4122..7e89548 100644 --- a/src/olympic/turbine/include/turbine/clipboard.hpp +++ b/src/olympic/turbine/include/turbine/clipboard.hpp @@ -34,7 +34,7 @@ void setClipboardText(Context &ctx, ox::StringViewCR text) noexcept; void setClipboardObject(Context &ctx, ox::UPtr &&obj) noexcept; -ox::Result getClipboardData(Context &ctx, ox::StringView typeId) noexcept; +ox::Result getClipboardData(Context &ctx, ox::StringViewCR typeId) noexcept; template ox::Result getClipboardObject(Context &ctx) noexcept { diff --git a/src/olympic/turbine/include/turbine/context.hpp b/src/olympic/turbine/include/turbine/context.hpp index f8da615..bc8a8e0 100644 --- a/src/olympic/turbine/include/turbine/context.hpp +++ b/src/olympic/turbine/include/turbine/context.hpp @@ -6,13 +6,9 @@ #include #include -#include -#include #include -#include "input.hpp" - namespace turbine { class Context; @@ -47,10 +43,5 @@ T *applicationData(Context &ctx) noexcept { return applicationDataRaw(ctx).get(); } -void setKeyEventHandler(Context &ctx, KeyEventHandler h) noexcept; - -[[nodiscard]] -KeyEventHandler keyEventHandler(Context &ctx) noexcept; - } diff --git a/src/olympic/turbine/include/turbine/event.hpp b/src/olympic/turbine/include/turbine/event.hpp deleted file mode 100644 index 9f415e9..0000000 --- a/src/olympic/turbine/include/turbine/event.hpp +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved. - */ - -#pragma once - -namespace turbine { - -class Context; - -using UpdateHandler = int(*)(Context&); - -// Sets event handler that sleeps for the time given in the return value. The -// sleep time is a minimum of ~16 milliseconds. -void setUpdateHandler(Context &ctx, UpdateHandler) noexcept; - -} diff --git a/src/olympic/turbine/include/turbine/gfx.hpp b/src/olympic/turbine/include/turbine/gfx.hpp index 52c1556..c512423 100644 --- a/src/olympic/turbine/include/turbine/gfx.hpp +++ b/src/olympic/turbine/include/turbine/gfx.hpp @@ -21,11 +21,9 @@ class Drawer { virtual void draw(Context&) noexcept = 0; }; void addDrawer(Context &ctx, Drawer *cd) noexcept; -void removeDrawer(Context &ctx, Drawer *cd) noexcept; +void removeDrawer(Context &ctx, Drawer const *cd) noexcept; } -ox::Error initGfx(Context &ctx) noexcept; - ox::Error setWindowIcon(Context &ctx, ox::SpanView> const &iconPngs) noexcept; void setWindowTitle(Context &ctx, ox::StringViewCR title) noexcept; diff --git a/src/olympic/turbine/include/turbine/input.hpp b/src/olympic/turbine/include/turbine/input.hpp deleted file mode 100644 index 20667cb..0000000 --- a/src/olympic/turbine/include/turbine/input.hpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved. - */ - -#pragma once - -#include - -namespace turbine { - -enum Key { - // GBA implementation currently relies on GamePad entry order - GamePad_A = 0, - GamePad_B, - GamePad_Select, - GamePad_Start, - GamePad_Right, - GamePad_Left, - GamePad_Up, - GamePad_Down, - GamePad_R, - GamePad_L, - - Num_0, - Num_1, - Num_2, - Num_3, - Num_4, - Num_5, - Num_6, - Num_7, - Num_8, - Num_9, - - Alpha_A, - Alpha_B, - Alpha_C, - Alpha_D, - Alpha_E, - Alpha_F, - Alpha_G, - Alpha_H, - Alpha_I, - Alpha_J, - Alpha_K, - Alpha_L, - Alpha_M, - Alpha_N, - Alpha_O, - Alpha_P, - Alpha_Q, - Alpha_R, - Alpha_S, - Alpha_T, - Alpha_U, - Alpha_V, - Alpha_W, - Alpha_X, - Alpha_Y, - Alpha_Z, - - Mod_Alt, - Mod_Ctrl, - Mod_Super, - Mod_Shift, - - Escape, - - End -}; - -class Context; - -[[nodiscard]] -bool buttonDown(Context const&ctx, Key) noexcept; - -using KeyEventHandler = void(*)(Context&, Key, bool); - -} diff --git a/src/olympic/turbine/include/turbine/turbine.hpp b/src/olympic/turbine/include/turbine/turbine.hpp index 34e34a1..338cd4b 100644 --- a/src/olympic/turbine/include/turbine/turbine.hpp +++ b/src/olympic/turbine/include/turbine/turbine.hpp @@ -8,13 +8,85 @@ #include #include "clipboard.hpp" -#include "event.hpp" #include "gfx.hpp" -#include "input.hpp" namespace turbine { +class Context; + using TimeMs = uint64_t; +using UpdateHandler = int(*)(Context&); + +enum Key { + // GBA implementation currently relies on GamePad entry order + GamePad_A = 0, + GamePad_B, + GamePad_Select, + GamePad_Start, + GamePad_Right, + GamePad_Left, + GamePad_Up, + GamePad_Down, + GamePad_R, + GamePad_L, + + Num_0, + Num_1, + Num_2, + Num_3, + Num_4, + Num_5, + Num_6, + Num_7, + Num_8, + Num_9, + + Alpha_A, + Alpha_B, + Alpha_C, + Alpha_D, + Alpha_E, + Alpha_F, + Alpha_G, + Alpha_H, + Alpha_I, + Alpha_J, + Alpha_K, + Alpha_L, + Alpha_M, + Alpha_N, + Alpha_O, + Alpha_P, + Alpha_Q, + Alpha_R, + Alpha_S, + Alpha_T, + Alpha_U, + Alpha_V, + Alpha_W, + Alpha_X, + Alpha_Y, + Alpha_Z, + + Mod_Alt, + Mod_Ctrl, + Mod_Super, + Mod_Shift, + + Escape, + + End +}; + +using KeyEventHandler = void(*)(Context&, Key, bool); + +void setKeyEventHandler(Context &ctx, KeyEventHandler h) noexcept; + +[[nodiscard]] +KeyEventHandler keyEventHandler(Context &ctx) noexcept; + +[[nodiscard]] +bool buttonDown(Context const&ctx, Key) noexcept; ox::Result> init(ox::UPtr &&fs, ox::StringViewCR appName) noexcept; @@ -33,4 +105,8 @@ using ShutdownHandler = bool (*)(Context&); void setShutdownHandler(Context &ctx, ShutdownHandler handler) noexcept; +// Sets event handler that sleeps for the time given in the return value. The +// sleep time is a minimum of ~16 milliseconds. +void setUpdateHandler(Context &ctx, UpdateHandler) noexcept; + } diff --git a/src/olympic/turbine/src/gba/CMakeLists.txt b/src/olympic/turbine/src/gba/CMakeLists.txt index 3491f14..3eed075 100644 --- a/src/olympic/turbine/src/gba/CMakeLists.txt +++ b/src/olympic/turbine/src/gba/CMakeLists.txt @@ -6,8 +6,6 @@ target_sources( Turbine-GBA PRIVATE context.cpp clipboard.cpp - event.cpp - gfx.cpp irq.arm.cpp turbine.arm.cpp turbine.cpp diff --git a/src/olympic/turbine/src/gba/clipboard.cpp b/src/olympic/turbine/src/gba/clipboard.cpp index 46e29f0..92cdd8a 100644 --- a/src/olympic/turbine/src/gba/clipboard.cpp +++ b/src/olympic/turbine/src/gba/clipboard.cpp @@ -5,6 +5,7 @@ #include #include +#include namespace turbine { @@ -15,4 +16,8 @@ ox::String getClipboardText(Context&) noexcept { void setClipboardText(Context&, ox::StringViewCR) noexcept { } +ox::Result getClipboardData(Context&, ox::StringViewCR) noexcept { + return ox::Error{1, "not implemented"}; +} + } diff --git a/src/olympic/turbine/src/gba/context.hpp b/src/olympic/turbine/src/gba/context.hpp index 5d2ba4a..e59eb39 100644 --- a/src/olympic/turbine/src/gba/context.hpp +++ b/src/olympic/turbine/src/gba/context.hpp @@ -6,9 +6,8 @@ #include -#include #include -#include +#include namespace turbine { diff --git a/src/olympic/turbine/src/gba/event.cpp b/src/olympic/turbine/src/gba/event.cpp deleted file mode 100644 index 52e792e..0000000 --- a/src/olympic/turbine/src/gba/event.cpp +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2016 - 2025 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/olympic/turbine/src/gba/gfx.cpp b/src/olympic/turbine/src/gba/gfx.cpp deleted file mode 100644 index 3d0bf44..0000000 --- a/src/olympic/turbine/src/gba/gfx.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved. - */ - -#include -#include - -#include -#include -#include - -#include - -namespace turbine { - -ox::Error initGfx(Context&) noexcept { - REG_DISPCTL = teagba::DispCtl_Mode0 - | teagba::DispCtl_SpriteMap1D - | teagba::DispCtl_Obj; - // tell display to trigger vblank interrupts - REG_DISPSTAT = REG_DISPSTAT | teagba::DispStat_irq_vblank; - // enable vblank interrupt - REG_IE = REG_IE | teagba::Int_vblank; - return {}; -} - -void setWindowTitle(Context&, ox::StringViewCR) noexcept { -} - -int getScreenWidth(Context const&) noexcept { - return 240; -} - -int getScreenHeight(Context const&) noexcept { - return 160; -} - -ox::Size getScreenSize(Context const&) noexcept { - return {240, 160}; -} - -ox::Bounds getWindowBounds(Context const&) noexcept { - return {0, 0, 240, 160}; -} - -ox::Error setWindowBounds(Context&, ox::Bounds const&) noexcept { - return ox::Error(1, "setWindowBounds not supported on GBA"); -} - -} diff --git a/src/olympic/turbine/src/gba/turbine.cpp b/src/olympic/turbine/src/gba/turbine.cpp index d4e3b25..c015e03 100644 --- a/src/olympic/turbine/src/gba/turbine.cpp +++ b/src/olympic/turbine/src/gba/turbine.cpp @@ -3,8 +3,10 @@ */ #include +#include #include + #include #include #include @@ -58,6 +60,40 @@ OX_ALLOW_UNSAFE_BUFFERS_END return ox::Error(1); } +static ox::Error initGfx(Context&) noexcept { + REG_DISPCTL = teagba::DispCtl_Mode0 + | teagba::DispCtl_SpriteMap1D + | teagba::DispCtl_Obj; + // tell display to trigger vblank interrupts + REG_DISPSTAT = REG_DISPSTAT | teagba::DispStat_irq_vblank; + // enable vblank interrupt + REG_IE = REG_IE | teagba::Int_vblank; + return {}; +} + +void setWindowTitle(Context&, ox::StringViewCR) noexcept { +} + +int getScreenWidth(Context const&) noexcept { + return 240; +} + +int getScreenHeight(Context const&) noexcept { + return 160; +} + +ox::Size getScreenSize(Context const&) noexcept { + return {240, 160}; +} + +ox::Bounds getWindowBounds(Context const&) noexcept { + return {0, 0, 240, 160}; +} + +ox::Error setWindowBounds(Context&, ox::Bounds const&) noexcept { + return ox::Error(1, "setWindowBounds not supported on GBA"); +} + ox::Result> init( ox::UPtr &&fs, ox::StringViewCR appName) noexcept { auto ctx = ox::make_unique(); @@ -68,7 +104,7 @@ ox::Result> init( OX_RETURN_ERROR(initGfx(*ctx)); initTimer(); initIrq(); - return ox::UPtr(std::move(ctx)); + return ctx; } void shutdown(Context&) noexcept { @@ -89,4 +125,16 @@ void requestShutdown(Context &ctx, bool) noexcept { void setShutdownHandler(Context&, ShutdownHandler) noexcept { } +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/olympic/turbine/src/glfw/CMakeLists.txt b/src/olympic/turbine/src/glfw/CMakeLists.txt index 4eb91b4..980c2db 100644 --- a/src/olympic/turbine/src/glfw/CMakeLists.txt +++ b/src/olympic/turbine/src/glfw/CMakeLists.txt @@ -5,8 +5,6 @@ target_sources( Turbine PRIVATE context.cpp clipboard.cpp - event.cpp - gfx.cpp turbine.cpp ) diff --git a/src/olympic/turbine/src/glfw/clipboard.cpp b/src/olympic/turbine/src/glfw/clipboard.cpp index edad904..7e45cf8 100644 --- a/src/olympic/turbine/src/glfw/clipboard.cpp +++ b/src/olympic/turbine/src/glfw/clipboard.cpp @@ -28,7 +28,7 @@ void setClipboardObject(Context &ctx, ox::UPtr &&obj) noexc ctx.clipboard = std::move(obj); } -ox::Result getClipboardData(Context &ctx, ox::StringView typeId) noexcept { +ox::Result getClipboardData(Context &ctx, ox::StringViewCR typeId) noexcept { if (ctx.clipboard && ctx.clipboard->typeId() == typeId) { return ctx.clipboard.get(); } diff --git a/src/olympic/turbine/src/glfw/context.hpp b/src/olympic/turbine/src/glfw/context.hpp index 50e29ff..c526b6b 100644 --- a/src/olympic/turbine/src/glfw/context.hpp +++ b/src/olympic/turbine/src/glfw/context.hpp @@ -7,7 +7,6 @@ #include #include #include -#include #include namespace turbine { diff --git a/src/olympic/turbine/src/glfw/event.cpp b/src/olympic/turbine/src/glfw/event.cpp deleted file mode 100644 index 52e792e..0000000 --- a/src/olympic/turbine/src/glfw/event.cpp +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2016 - 2025 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/olympic/turbine/src/glfw/gfx.cpp b/src/olympic/turbine/src/glfw/gfx.cpp deleted file mode 100644 index 767cef8..0000000 --- a/src/olympic/turbine/src/glfw/gfx.cpp +++ /dev/null @@ -1,324 +0,0 @@ -/* - * Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved. - */ - -#include -#include -#include -#if TURBINE_USE_IMGUI -#include -#include -#endif - -#include "config.hpp" - -#include - -#include "context.hpp" - -namespace turbine { - -namespace gl { - -void addDrawer(Context &ctx, Drawer *cd) noexcept { - ctx.drawers.emplace_back(cd); -} - -void removeDrawer(Context &ctx, Drawer *cd) noexcept { - for (auto i = 0u; i < ctx.drawers.size(); ++i) { - if (ctx.drawers[i] == cd) { - std::ignore = ctx.drawers.erase(i); - break; - } - } -} - -} - -static void handleGlfwError(int err, char const*desc) noexcept { - oxErrf("GLFW error ({}): {}\n", err, desc); -} - -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 constexpr auto keyMap = [] { - ox::Array map = {}; - for (auto i = 0u; i < 26; ++i) { - map[GLFW_KEY_A + i] = static_cast(static_cast(Key::Alpha_A) + i); - } - for (auto i = 0u; i < 10; ++i) { - map[GLFW_KEY_0 + i] = static_cast(static_cast(Key::Num_0) + i); - } - map[GLFW_KEY_LEFT_ALT] = Key::Mod_Alt; - map[GLFW_KEY_RIGHT_ALT] = Key::Mod_Alt; - map[GLFW_KEY_LEFT_CONTROL] = Key::Mod_Ctrl; - map[GLFW_KEY_RIGHT_CONTROL] = Key::Mod_Ctrl; - map[GLFW_KEY_LEFT_SUPER] = Key::Mod_Super; - map[GLFW_KEY_RIGHT_SUPER] = Key::Mod_Super; - map[GLFW_KEY_LEFT_SHIFT] = Key::Mod_Shift; - map[GLFW_KEY_RIGHT_SHIFT] = Key::Mod_Shift; - map[GLFW_KEY_ESCAPE] = Key::Escape; - return map; - }(); - auto const eventHandler = keyEventHandler(ctx); - auto const keyIdx = static_cast(key); - if (keyIdx < keyMap.size()) { - auto const k = keyMap[keyIdx]; - setKeyDownStatus(ctx, k, down); - if (eventHandler) { - eventHandler(ctx, k, down); - } - } -} - -static void handleGlfwCursorPosEvent(GLFWwindow*, double, double) noexcept { -} - -static void handleGlfwMouseButtonEvent(GLFWwindow *window, int, int, int) noexcept { - auto &ctx = *static_cast(glfwGetWindowUserPointer(window)); - ctx.mandatoryRefreshPeriodEnd = ticksMs(ctx) + config::MandatoryRefreshPeriod; -} - -static void handleGlfwKeyEvent(GLFWwindow *window, int key, int, int action, int) noexcept { - auto &ctx = *static_cast(glfwGetWindowUserPointer(window)); - ctx.mandatoryRefreshPeriodEnd = ticksMs(ctx) + config::MandatoryRefreshPeriod; - if (action == GLFW_PRESS) { - handleKeyPress(ctx, key, true); - } else if (action == GLFW_RELEASE) { - handleKeyPress(ctx, key, false); - } -} - -static void handleGlfwWindowCloseEvent(GLFWwindow *window) noexcept { - auto &ctx = *static_cast(glfwGetWindowUserPointer(window)); - ctx.mandatoryRefreshPeriodEnd = ticksMs(ctx) + config::MandatoryRefreshPeriod; - ctx.running = ctx.shutdownHandler ? !ctx.shutdownHandler(ctx) : false; - glfwSetWindowShouldClose(window, !ctx.running); - glfwPostEmptyEvent(); -} - -#if TURBINE_USE_IMGUI -static void themeImgui() noexcept { - // Dark Ruda style by Raikiri from ImThemes - auto &style = ImGui::GetStyle(); - style.Alpha = 1.0; - style.DisabledAlpha = 0.6000000238418579; - style.WindowPadding = ImVec2(8.0, 8.0); - style.WindowRounding = 0.0; - style.WindowBorderSize = 1.0; - style.WindowMinSize = ImVec2(32.0, 32.0); - style.WindowTitleAlign = ImVec2(0.0, 0.5); - style.WindowMenuButtonPosition = ImGuiDir_Left; - style.ChildRounding = 0.0; - style.ChildBorderSize = 1.0; - style.PopupRounding = 0.0; - style.PopupBorderSize = 1.0; - style.FramePadding = ImVec2(4.0, 3.0); - // custom value - style.FrameRounding = 3.0; - style.FrameBorderSize = 0.0; - style.ItemSpacing = ImVec2(8.0, 4.0); - style.ItemInnerSpacing = ImVec2(4.0, 4.0); - style.CellPadding = ImVec2(4.0, 2.0); - style.IndentSpacing = 21.0; - style.ColumnsMinSpacing = 6.0; - style.ScrollbarSize = 14.0; - style.ScrollbarRounding = 9.0; - style.GrabMinSize = 10.0; - style.GrabRounding = 4.0; - style.TabRounding = 4.0; - style.TabBorderSize = 0.0; - style.TabMinWidthForCloseButton = 0.0; - style.ColorButtonPosition = ImGuiDir_Right; - style.ButtonTextAlign = ImVec2(0.5, 0.5); - style.SelectableTextAlign = ImVec2(0.0, 0.0); - // colors - constexpr auto imVec4 = [](double r, double g, double b, double a) { - return ImVec4( - static_cast(r), - static_cast(g), - static_cast(b), - static_cast(a)); - }; - auto colors = ox::Span(style.Colors); - colors[ImGuiCol_Text] = imVec4(0.9490196108818054, 0.95686274766922, 0.9764705896377563, 1.0); - colors[ImGuiCol_TextDisabled] = imVec4(0.3568627536296844, 0.4196078479290009, 0.4666666686534882, 1.0); - colors[ImGuiCol_WindowBg] = imVec4(0.1098039224743843, 0.1490196138620377, 0.168627455830574, 1.0); - colors[ImGuiCol_ChildBg] = imVec4(0.1490196138620377, 0.1764705926179886, 0.2196078449487686, 1.0); - colors[ImGuiCol_PopupBg] = imVec4(0.0784313753247261, 0.0784313753247261, 0.0784313753247261, 0.9399999976158142); - colors[ImGuiCol_Border] = imVec4(0.0784313753247261, 0.09803921729326248, 0.1176470592617989, 1.0); - colors[ImGuiCol_BorderShadow] = imVec4(0.0, 0.0, 0.0, 0.0); - colors[ImGuiCol_FrameBg] = imVec4(0.2000000029802322, 0.2470588237047195, 0.2862745225429535, 1.0); - colors[ImGuiCol_FrameBgHovered] = imVec4(0.1176470592617989, 0.2000000029802322, 0.2784313857555389, 1.0); - colors[ImGuiCol_FrameBgActive] = imVec4(0.08627451211214066, 0.1176470592617989, 0.1372549086809158, 1.0); - colors[ImGuiCol_TitleBg] = imVec4(0.08627451211214066, 0.1176470592617989, 0.1372549086809158, 0.6499999761581421); - colors[ImGuiCol_TitleBgActive] = imVec4(0.0784313753247261, 0.09803921729326248, 0.1176470592617989, 1.0); - colors[ImGuiCol_TitleBgCollapsed] = imVec4(0.0, 0.0, 0.0, 0.5099999904632568); - colors[ImGuiCol_MenuBarBg] = imVec4(0.1490196138620377, 0.1764705926179886, 0.2196078449487686, 1.0); - colors[ImGuiCol_ScrollbarBg] = imVec4(0.01960784383118153, 0.01960784383118153, 0.01960784383118153, 0.3899999856948853); - colors[ImGuiCol_ScrollbarGrab] = imVec4(0.2000000029802322, 0.2470588237047195, 0.2862745225429535, 1.0); - colors[ImGuiCol_ScrollbarGrabHovered] = imVec4(0.1764705926179886, 0.2196078449487686, 0.2470588237047195, 1.0); - colors[ImGuiCol_ScrollbarGrabActive] = imVec4(0.08627451211214066, 0.2078431397676468, 0.3098039329051971, 1.0); - colors[ImGuiCol_CheckMark] = imVec4(0.2784313857555389, 0.5568627715110779, 1.0, 1.0); - colors[ImGuiCol_SliderGrab] = imVec4(0.2784313857555389, 0.5568627715110779, 1.0, 1.0); - colors[ImGuiCol_SliderGrabActive] = imVec4(0.3686274588108063, 0.6078431606292725, 1.0, 1.0); - colors[ImGuiCol_Button] = imVec4(0.2000000029802322, 0.2470588237047195, 0.2862745225429535, 1.0); - colors[ImGuiCol_ButtonHovered] = imVec4(0.2784313857555389, 0.5568627715110779, 1.0, 1.0); - colors[ImGuiCol_ButtonActive] = imVec4(0.05882352963089943, 0.529411792755127, 0.9764705896377563, 1.0); - // custom value - colors[ImGuiCol_Header] = imVec4(0.4000000029802322, 0.4470588237047195, 0.4862745225429535, 0.550000011920929); - colors[ImGuiCol_HeaderHovered] = imVec4(0.2588235437870026, 0.5882353186607361, 0.9764705896377563, 0.800000011920929); - colors[ImGuiCol_HeaderActive] = imVec4(0.2588235437870026, 0.5882353186607361, 0.9764705896377563, 1.0); - colors[ImGuiCol_Separator] = imVec4(0.2000000029802322, 0.2470588237047195, 0.2862745225429535, 1.0); - colors[ImGuiCol_SeparatorHovered] = imVec4(0.09803921729326248, 0.4000000059604645, 0.7490196228027344, 0.7799999713897705); - colors[ImGuiCol_SeparatorActive] = imVec4(0.09803921729326248, 0.4000000059604645, 0.7490196228027344, 1.0); - colors[ImGuiCol_ResizeGrip] = imVec4(0.2588235437870026, 0.5882353186607361, 0.9764705896377563, 0.25); - colors[ImGuiCol_ResizeGripHovered] = imVec4(0.2588235437870026, 0.5882353186607361, 0.9764705896377563, 0.6700000166893005); - colors[ImGuiCol_ResizeGripActive] = imVec4(0.2588235437870026, 0.5882353186607361, 0.9764705896377563, 0.949999988079071); - colors[ImGuiCol_Tab] = imVec4(0.1098039224743843, 0.1490196138620377, 0.168627455830574, 1.0); - colors[ImGuiCol_TabHovered] = imVec4(0.2588235437870026, 0.5882353186607361, 0.9764705896377563, 0.800000011920929); - colors[ImGuiCol_TabActive] = imVec4(0.2000000029802322, 0.2470588237047195, 0.2862745225429535, 1.0); - colors[ImGuiCol_TabUnfocused] = imVec4(0.1098039224743843, 0.1490196138620377, 0.168627455830574, 1.0); - colors[ImGuiCol_TabUnfocusedActive] = imVec4(0.1098039224743843, 0.1490196138620377, 0.168627455830574, 1.0); - colors[ImGuiCol_PlotLines] = imVec4(0.6078431606292725, 0.6078431606292725, 0.6078431606292725, 1.0); - colors[ImGuiCol_PlotLinesHovered] = imVec4(1.0, 0.4274509847164154, 0.3490196168422699, 1.0); - colors[ImGuiCol_PlotHistogram] = imVec4(0.8980392217636108, 0.6980392336845398, 0.0, 1.0); - colors[ImGuiCol_PlotHistogramHovered] = imVec4(1.0, 0.6000000238418579, 0.0, 1.0); - colors[ImGuiCol_TableHeaderBg] = imVec4(0.1882352977991104, 0.1882352977991104, 0.2000000029802322, 1.0); - colors[ImGuiCol_TableBorderStrong] = imVec4(0.3098039329051971, 0.3098039329051971, 0.3490196168422699, 1.0); - colors[ImGuiCol_TableBorderLight] = imVec4(0.2274509817361832, 0.2274509817361832, 0.2470588237047195, 1.0); - colors[ImGuiCol_TableRowBg] = imVec4(0.0, 0.0, 0.0, 0.0); - colors[ImGuiCol_TableRowBgAlt] = imVec4(1.0, 1.0, 1.0, 0.05999999865889549); - colors[ImGuiCol_TextSelectedBg] = imVec4(0.2588235437870026, 0.5882353186607361, 0.9764705896377563, 0.3499999940395355); - colors[ImGuiCol_DragDropTarget] = imVec4(1.0, 1.0, 0.0, 0.8999999761581421); - colors[ImGuiCol_NavHighlight] = imVec4(0.2588235437870026, 0.5882353186607361, 0.9764705896377563, 1.0); - colors[ImGuiCol_NavWindowingHighlight] = imVec4(1.0, 1.0, 1.0, 0.699999988079071); - colors[ImGuiCol_NavWindowingDimBg] = imVec4(0.800000011920929, 0.800000011920929, 0.800000011920929, 0.2000000029802322); - colors[ImGuiCol_ModalWindowDimBg] = imVec4(0.800000011920929, 0.800000011920929, 0.800000011920929, 0.3499999940395355); -} -#endif - -ox::Error initGfx(Context &ctx) noexcept { - glfwSetErrorCallback(handleGlfwError); - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE); - glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); - constexpr auto Scale = 5; - 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 ox::Error(1, "Could not open GLFW window"); - } - glfwSetCursorPosCallback(ctx.window, handleGlfwCursorPosEvent); - glfwSetMouseButtonCallback(ctx.window, handleGlfwMouseButtonEvent); - glfwSetKeyCallback(ctx.window, handleGlfwKeyEvent); - glfwSetWindowCloseCallback(ctx.window, handleGlfwWindowCloseEvent); - glfwSetWindowUserPointer(ctx.window, &ctx); - glfwMakeContextCurrent(ctx.window); - if (!gladLoadGLES2Loader(reinterpret_cast(glfwGetProcAddress))) { - return ox::Error(2, "Could not init Glad"); - } -#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(); - io.IniFilename = nullptr; - themeImgui(); -#endif - return {}; -} - -struct IconData { - std::vector pixels; - int w{}, h{}; -}; - -[[nodiscard]] -[[maybe_unused]] -static ox::Result toGlfwImgPixels(ox::SpanView const &iconPng) noexcept { - ox::Result out; - unsigned w{}, h{}; - if (lodepng::decode(out.value.pixels, w, h, iconPng.data(), iconPng.size())) { - return ox::Error{1, "unable to decode window icon PNG data"}; - } - out.value.w = static_cast(w); - out.value.h = static_cast(h); - return out; -} - -ox::Error setWindowIcon(Context &ctx, ox::SpanView> const &iconPngs) noexcept { - if constexpr(ox::defines::OS != ox::OS::Darwin) { - ox::Vector src; - ox::Vector imgs; - for (auto const &iconPng : iconPngs) { - OX_RETURN_ERROR(toGlfwImgPixels(iconPng).moveTo(src.emplace_back())); - auto &icon = *src.back().unwrap(); - imgs.emplace_back(GLFWimage{ - .width = icon.w, - .height = icon.h, - .pixels = icon.pixels.data(), - }); - } - glfwSetWindowIcon(ctx.window, static_cast(imgs.size()), imgs.data()); - } - return {}; -} - -void setWindowTitle(Context &ctx, ox::StringViewCR title) noexcept { - auto cstr = ox_malloca(title.bytes() + 1, char); - OX_ALLOW_UNSAFE_BUFFERS_BEGIN - ox::strncpy(cstr.get(), title.data(), title.bytes()); - OX_ALLOW_UNSAFE_BUFFERS_END - glfwSetWindowTitle(ctx.window, cstr.get()); -} - -void focusWindow(Context &ctx) noexcept { - glfwFocusWindow(ctx.window); -} - -int getScreenWidth(Context const &ctx) noexcept { - int w = 0, h = 0; - glfwGetFramebufferSize(ctx.window, &w, &h); - return w; -} - -int getScreenHeight(Context const &ctx) noexcept { - int w = 0, h = 0; - glfwGetFramebufferSize(ctx.window, &w, &h); - return h; -} - -ox::Size getScreenSize(Context const &ctx) noexcept { - int w = 0, h = 0; - glfwGetFramebufferSize(ctx.window, &w, &h); - return {w, h}; -} - -ox::Bounds getWindowBounds(Context const &ctx) noexcept { - ox::Bounds bnds; - glfwGetWindowPos(ctx.window, &bnds.x, &bnds.y); - glfwGetWindowSize(ctx.window, &bnds.width, &bnds.height); - return bnds; -} - -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 setRefreshWithin(Context &ctx, int ms) noexcept { - ctx.refreshWithinMs = ox::min(ms, ctx.refreshWithinMs); -} - -} diff --git a/src/olympic/turbine/src/glfw/turbine.cpp b/src/olympic/turbine/src/glfw/turbine.cpp index b7b0efe..53666d8 100644 --- a/src/olympic/turbine/src/glfw/turbine.cpp +++ b/src/olympic/turbine/src/glfw/turbine.cpp @@ -2,7 +2,9 @@ * Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved. */ +#include #include +#include #if TURBINE_USE_IMGUI #include #include @@ -17,6 +19,207 @@ namespace turbine { +namespace gl { + +void addDrawer(Context &ctx, Drawer *cd) noexcept { + ctx.drawers.emplace_back(cd); +} + +void removeDrawer(Context &ctx, Drawer const *cd) noexcept { + for (auto i = 0u; i < ctx.drawers.size(); ++i) { + if (ctx.drawers[i] == cd) { + std::ignore = ctx.drawers.erase(i); + break; + } + } +} + +} + +#if TURBINE_USE_IMGUI +static void themeImgui() noexcept { + // Dark Ruda style by Raikiri from ImThemes + auto &style = ImGui::GetStyle(); + style.Alpha = 1.0; + style.DisabledAlpha = 0.6000000238418579; + style.WindowPadding = ImVec2(8.0, 8.0); + style.WindowRounding = 0.0; + style.WindowBorderSize = 1.0; + style.WindowMinSize = ImVec2(32.0, 32.0); + style.WindowTitleAlign = ImVec2(0.0, 0.5); + style.WindowMenuButtonPosition = ImGuiDir_Left; + style.ChildRounding = 0.0; + style.ChildBorderSize = 1.0; + style.PopupRounding = 0.0; + style.PopupBorderSize = 1.0; + style.FramePadding = ImVec2(4.0, 3.0); + // custom value + style.FrameRounding = 3.0; + style.FrameBorderSize = 0.0; + style.ItemSpacing = ImVec2(8.0, 4.0); + style.ItemInnerSpacing = ImVec2(4.0, 4.0); + style.CellPadding = ImVec2(4.0, 2.0); + style.IndentSpacing = 21.0; + style.ColumnsMinSpacing = 6.0; + style.ScrollbarSize = 14.0; + style.ScrollbarRounding = 9.0; + style.GrabMinSize = 10.0; + style.GrabRounding = 4.0; + style.TabRounding = 4.0; + style.TabBorderSize = 0.0; + style.TabMinWidthForCloseButton = 0.0; + style.ColorButtonPosition = ImGuiDir_Right; + style.ButtonTextAlign = ImVec2(0.5, 0.5); + style.SelectableTextAlign = ImVec2(0.0, 0.0); + // colors + constexpr auto imVec4 = [](double r, double g, double b, double a) { + return ImVec4( + static_cast(r), + static_cast(g), + static_cast(b), + static_cast(a)); + }; + auto colors = ox::Span(style.Colors); + colors[ImGuiCol_Text] = imVec4(0.9490196108818054, 0.95686274766922, 0.9764705896377563, 1.0); + colors[ImGuiCol_TextDisabled] = imVec4(0.3568627536296844, 0.4196078479290009, 0.4666666686534882, 1.0); + colors[ImGuiCol_WindowBg] = imVec4(0.1098039224743843, 0.1490196138620377, 0.168627455830574, 1.0); + colors[ImGuiCol_ChildBg] = imVec4(0.1490196138620377, 0.1764705926179886, 0.2196078449487686, 1.0); + colors[ImGuiCol_PopupBg] = imVec4(0.0784313753247261, 0.0784313753247261, 0.0784313753247261, 0.9399999976158142); + colors[ImGuiCol_Border] = imVec4(0.0784313753247261, 0.09803921729326248, 0.1176470592617989, 1.0); + colors[ImGuiCol_BorderShadow] = imVec4(0.0, 0.0, 0.0, 0.0); + colors[ImGuiCol_FrameBg] = imVec4(0.2000000029802322, 0.2470588237047195, 0.2862745225429535, 1.0); + colors[ImGuiCol_FrameBgHovered] = imVec4(0.1176470592617989, 0.2000000029802322, 0.2784313857555389, 1.0); + colors[ImGuiCol_FrameBgActive] = imVec4(0.08627451211214066, 0.1176470592617989, 0.1372549086809158, 1.0); + colors[ImGuiCol_TitleBg] = imVec4(0.08627451211214066, 0.1176470592617989, 0.1372549086809158, 0.6499999761581421); + colors[ImGuiCol_TitleBgActive] = imVec4(0.0784313753247261, 0.09803921729326248, 0.1176470592617989, 1.0); + colors[ImGuiCol_TitleBgCollapsed] = imVec4(0.0, 0.0, 0.0, 0.5099999904632568); + colors[ImGuiCol_MenuBarBg] = imVec4(0.1490196138620377, 0.1764705926179886, 0.2196078449487686, 1.0); + colors[ImGuiCol_ScrollbarBg] = imVec4(0.01960784383118153, 0.01960784383118153, 0.01960784383118153, 0.3899999856948853); + colors[ImGuiCol_ScrollbarGrab] = imVec4(0.2000000029802322, 0.2470588237047195, 0.2862745225429535, 1.0); + colors[ImGuiCol_ScrollbarGrabHovered] = imVec4(0.1764705926179886, 0.2196078449487686, 0.2470588237047195, 1.0); + colors[ImGuiCol_ScrollbarGrabActive] = imVec4(0.08627451211214066, 0.2078431397676468, 0.3098039329051971, 1.0); + colors[ImGuiCol_CheckMark] = imVec4(0.2784313857555389, 0.5568627715110779, 1.0, 1.0); + colors[ImGuiCol_SliderGrab] = imVec4(0.2784313857555389, 0.5568627715110779, 1.0, 1.0); + colors[ImGuiCol_SliderGrabActive] = imVec4(0.3686274588108063, 0.6078431606292725, 1.0, 1.0); + colors[ImGuiCol_Button] = imVec4(0.2000000029802322, 0.2470588237047195, 0.2862745225429535, 1.0); + colors[ImGuiCol_ButtonHovered] = imVec4(0.2784313857555389, 0.5568627715110779, 1.0, 1.0); + colors[ImGuiCol_ButtonActive] = imVec4(0.05882352963089943, 0.529411792755127, 0.9764705896377563, 1.0); + // custom value + colors[ImGuiCol_Header] = imVec4(0.4000000029802322, 0.4470588237047195, 0.4862745225429535, 0.550000011920929); + colors[ImGuiCol_HeaderHovered] = imVec4(0.2588235437870026, 0.5882353186607361, 0.9764705896377563, 0.800000011920929); + colors[ImGuiCol_HeaderActive] = imVec4(0.2588235437870026, 0.5882353186607361, 0.9764705896377563, 1.0); + colors[ImGuiCol_Separator] = imVec4(0.2000000029802322, 0.2470588237047195, 0.2862745225429535, 1.0); + colors[ImGuiCol_SeparatorHovered] = imVec4(0.09803921729326248, 0.4000000059604645, 0.7490196228027344, 0.7799999713897705); + colors[ImGuiCol_SeparatorActive] = imVec4(0.09803921729326248, 0.4000000059604645, 0.7490196228027344, 1.0); + colors[ImGuiCol_ResizeGrip] = imVec4(0.2588235437870026, 0.5882353186607361, 0.9764705896377563, 0.25); + colors[ImGuiCol_ResizeGripHovered] = imVec4(0.2588235437870026, 0.5882353186607361, 0.9764705896377563, 0.6700000166893005); + colors[ImGuiCol_ResizeGripActive] = imVec4(0.2588235437870026, 0.5882353186607361, 0.9764705896377563, 0.949999988079071); + colors[ImGuiCol_Tab] = imVec4(0.1098039224743843, 0.1490196138620377, 0.168627455830574, 1.0); + colors[ImGuiCol_TabHovered] = imVec4(0.2588235437870026, 0.5882353186607361, 0.9764705896377563, 0.800000011920929); + colors[ImGuiCol_TabActive] = imVec4(0.2000000029802322, 0.2470588237047195, 0.2862745225429535, 1.0); + colors[ImGuiCol_TabUnfocused] = imVec4(0.1098039224743843, 0.1490196138620377, 0.168627455830574, 1.0); + colors[ImGuiCol_TabUnfocusedActive] = imVec4(0.1098039224743843, 0.1490196138620377, 0.168627455830574, 1.0); + colors[ImGuiCol_PlotLines] = imVec4(0.6078431606292725, 0.6078431606292725, 0.6078431606292725, 1.0); + colors[ImGuiCol_PlotLinesHovered] = imVec4(1.0, 0.4274509847164154, 0.3490196168422699, 1.0); + colors[ImGuiCol_PlotHistogram] = imVec4(0.8980392217636108, 0.6980392336845398, 0.0, 1.0); + colors[ImGuiCol_PlotHistogramHovered] = imVec4(1.0, 0.6000000238418579, 0.0, 1.0); + colors[ImGuiCol_TableHeaderBg] = imVec4(0.1882352977991104, 0.1882352977991104, 0.2000000029802322, 1.0); + colors[ImGuiCol_TableBorderStrong] = imVec4(0.3098039329051971, 0.3098039329051971, 0.3490196168422699, 1.0); + colors[ImGuiCol_TableBorderLight] = imVec4(0.2274509817361832, 0.2274509817361832, 0.2470588237047195, 1.0); + colors[ImGuiCol_TableRowBg] = imVec4(0.0, 0.0, 0.0, 0.0); + colors[ImGuiCol_TableRowBgAlt] = imVec4(1.0, 1.0, 1.0, 0.05999999865889549); + colors[ImGuiCol_TextSelectedBg] = imVec4(0.2588235437870026, 0.5882353186607361, 0.9764705896377563, 0.3499999940395355); + colors[ImGuiCol_DragDropTarget] = imVec4(1.0, 1.0, 0.0, 0.8999999761581421); + colors[ImGuiCol_NavHighlight] = imVec4(0.2588235437870026, 0.5882353186607361, 0.9764705896377563, 1.0); + colors[ImGuiCol_NavWindowingHighlight] = imVec4(1.0, 1.0, 1.0, 0.699999988079071); + colors[ImGuiCol_NavWindowingDimBg] = imVec4(0.800000011920929, 0.800000011920929, 0.800000011920929, 0.2000000029802322); + colors[ImGuiCol_ModalWindowDimBg] = imVec4(0.800000011920929, 0.800000011920929, 0.800000011920929, 0.3499999940395355); +} +#endif + +struct IconData { + std::vector pixels; + int w{}, h{}; +}; + +[[nodiscard]] +[[maybe_unused]] +static ox::Result toGlfwImgPixels(ox::SpanView const &iconPng) noexcept { + ox::Result out; + unsigned w{}, h{}; + if (lodepng::decode(out.value.pixels, w, h, iconPng.data(), iconPng.size())) { + return ox::Error{1, "unable to decode window icon PNG data"}; + } + out.value.w = static_cast(w); + out.value.h = static_cast(h); + return out; +} + +ox::Error setWindowIcon(Context &ctx, ox::SpanView> const &iconPngs) noexcept { + if constexpr(ox::defines::OS != ox::OS::Darwin) { + ox::Vector src; + ox::Vector imgs; + for (auto const &iconPng : iconPngs) { + OX_RETURN_ERROR(toGlfwImgPixels(iconPng).moveTo(src.emplace_back())); + auto &icon = *src.back().unwrap(); + imgs.emplace_back(GLFWimage{ + .width = icon.w, + .height = icon.h, + .pixels = icon.pixels.data(), + }); + } + glfwSetWindowIcon(ctx.window, static_cast(imgs.size()), imgs.data()); + } + return {}; +} + +void setWindowTitle(Context &ctx, ox::StringViewCR title) noexcept { + auto cstr = ox_malloca(title.bytes() + 1, char); + OX_ALLOW_UNSAFE_BUFFERS_BEGIN + ox::strncpy(cstr.get(), title.data(), title.bytes()); + OX_ALLOW_UNSAFE_BUFFERS_END + glfwSetWindowTitle(ctx.window, cstr.get()); +} + +void focusWindow(Context &ctx) noexcept { + glfwFocusWindow(ctx.window); +} + +int getScreenWidth(Context const &ctx) noexcept { + int w = 0, h = 0; + glfwGetFramebufferSize(ctx.window, &w, &h); + return w; +} + +int getScreenHeight(Context const &ctx) noexcept { + int w = 0, h = 0; + glfwGetFramebufferSize(ctx.window, &w, &h); + return h; +} + +ox::Size getScreenSize(Context const &ctx) noexcept { + int w = 0, h = 0; + glfwGetFramebufferSize(ctx.window, &w, &h); + return {w, h}; +} + +ox::Bounds getWindowBounds(Context const &ctx) noexcept { + ox::Bounds bnds; + glfwGetWindowPos(ctx.window, &bnds.x, &bnds.y); + glfwGetWindowSize(ctx.window, &bnds.width, &bnds.height); + return bnds; +} + +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 setRefreshWithin(Context &ctx, int ms) noexcept { + ctx.refreshWithinMs = ox::min(ms, ctx.refreshWithinMs); +} + static void draw(Context &ctx) noexcept { // draw start #if TURBINE_USE_IMGUI @@ -35,11 +238,77 @@ static void draw(Context &ctx) noexcept { glfwSwapBuffers(ctx.window); } -static void draw(GLFWwindow *window, int, int) noexcept { +static void handleGlfwResize(GLFWwindow *window, int, int) noexcept { auto &ctx = *static_cast(glfwGetWindowUserPointer(window)); draw(ctx); } +static void handleGlfwError(int const err, char const *desc) noexcept { + oxErrf("GLFW error ({}): {}\n", err, desc); +} + +static auto setKeyDownStatus(Context &ctx, Key const key, bool const down) noexcept { + ctx.keysDown &= ~(1llu << static_cast(key)); + ctx.keysDown |= static_cast(down) << static_cast(key); +} + +static void handleKeyPress(Context &ctx, int const key, bool const down) noexcept { + static constexpr auto keyMap = [] { + ox::Array map = {}; + for (auto i = 0u; i < 26; ++i) { + map[GLFW_KEY_A + i] = static_cast(static_cast(Key::Alpha_A) + i); + } + for (auto i = 0u; i < 10; ++i) { + map[GLFW_KEY_0 + i] = static_cast(static_cast(Key::Num_0) + i); + } + map[GLFW_KEY_LEFT_ALT] = Key::Mod_Alt; + map[GLFW_KEY_RIGHT_ALT] = Key::Mod_Alt; + map[GLFW_KEY_LEFT_CONTROL] = Key::Mod_Ctrl; + map[GLFW_KEY_RIGHT_CONTROL] = Key::Mod_Ctrl; + map[GLFW_KEY_LEFT_SUPER] = Key::Mod_Super; + map[GLFW_KEY_RIGHT_SUPER] = Key::Mod_Super; + map[GLFW_KEY_LEFT_SHIFT] = Key::Mod_Shift; + map[GLFW_KEY_RIGHT_SHIFT] = Key::Mod_Shift; + map[GLFW_KEY_ESCAPE] = Key::Escape; + return map; + }(); + auto const eventHandler = keyEventHandler(ctx); + auto const keyIdx = static_cast(key); + if (keyIdx < keyMap.size()) { + auto const k = keyMap[keyIdx]; + setKeyDownStatus(ctx, k, down); + if (eventHandler) { + eventHandler(ctx, k, down); + } + } +} + +static void handleGlfwCursorPosEvent(GLFWwindow*, double, double) noexcept { +} + +static void handleGlfwMouseButtonEvent(GLFWwindow *window, int, int, int) noexcept { + auto &ctx = *static_cast(glfwGetWindowUserPointer(window)); + ctx.mandatoryRefreshPeriodEnd = ticksMs(ctx) + config::MandatoryRefreshPeriod; +} + +static void handleGlfwKeyEvent(GLFWwindow *window, int const key, int, int const action, int) noexcept { + auto &ctx = *static_cast(glfwGetWindowUserPointer(window)); + ctx.mandatoryRefreshPeriodEnd = ticksMs(ctx) + config::MandatoryRefreshPeriod; + if (action == GLFW_PRESS) { + handleKeyPress(ctx, key, true); + } else if (action == GLFW_RELEASE) { + handleKeyPress(ctx, key, false); + } +} + +static void handleGlfwWindowCloseEvent(GLFWwindow *window) noexcept { + auto &ctx = *static_cast(glfwGetWindowUserPointer(window)); + ctx.mandatoryRefreshPeriodEnd = ticksMs(ctx) + config::MandatoryRefreshPeriod; + ctx.running = ctx.shutdownHandler ? !ctx.shutdownHandler(ctx) : false; + glfwSetWindowShouldClose(window, !ctx.running); + glfwPostEmptyEvent(); +} + ox::Result> init( ox::UPtr &&fs, ox::StringViewCR appName) noexcept { auto ctx = ox::make_unique(); @@ -47,11 +316,44 @@ ox::Result> init( using namespace std::chrono; ctx->startTime = static_cast( duration_cast(system_clock::now().time_since_epoch()).count()); - glfwInit(); - OX_RETURN_ERROR(initGfx(*ctx)); - glfwSetWindowSizeCallback(ctx->window, draw); ctx->mandatoryRefreshPeriodEnd = ticksMs(*ctx) + config::MandatoryRefreshPeriod; - return ox::UPtr(ctx.release()); + // init GLFW context + glfwInit(); + glfwSetErrorCallback(handleGlfwError); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE); + glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); + constexpr auto Scale = 5; + 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 ox::Error(1, "Could not open GLFW window"); + } + glfwSetCursorPosCallback(ctx->window, handleGlfwCursorPosEvent); + glfwSetMouseButtonCallback(ctx->window, handleGlfwMouseButtonEvent); + glfwSetKeyCallback(ctx->window, handleGlfwKeyEvent); + glfwSetWindowCloseCallback(ctx->window, handleGlfwWindowCloseEvent); + glfwSetWindowSizeCallback(ctx->window, handleGlfwResize); + glfwSetWindowUserPointer(ctx->window, ctx.get()); + glfwMakeContextCurrent(ctx->window); + if (!gladLoadGLES2Loader(reinterpret_cast(glfwGetProcAddress))) { + return ox::Error(2, "Could not init Glad"); + } + // init ImGui +#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(); + io.IniFilename = nullptr; + themeImgui(); +#endif + return ctx; } static void tickFps(Context &ctx, uint64_t const nowMs) noexcept { @@ -132,4 +434,16 @@ void setShutdownHandler(Context &ctx, ShutdownHandler const handler) noexcept { ctx.shutdownHandler = handler; } +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; +} + }