diff --git a/CMakeLists.txt b/CMakeLists.txt index cd956144..f88bf177 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -97,7 +97,7 @@ set(SFML_ENABLE_PCH true) CPMAddPackage( NAME SFML GITHUB_REPOSITORY vittorioromeo/SFML - GIT_TAG e327277b1d001079a85f3959ba2fc802f7dbbc6b + GIT_TAG 0608821ff4e8de462d5aa44343df42d989f8102a ) set_target_properties(sfml-system PROPERTIES UNITY_BUILD ON) @@ -201,7 +201,7 @@ if(NOT SSVOH_ANDROID) CPMAddPackage( NAME imgui-sfml GITHUB_REPOSITORY vittorioromeo/imgui-sfml - GIT_TAG 6ea83b31a67876fe8c3061297e2ac39033a8e0f3 + GIT_TAG 32b2c1588b78b2946f8c7c61420fbd8a45ae4e9c ) set_target_properties(ImGui-SFML PROPERTIES UNITY_BUILD ON) diff --git a/include/SSVOpenHexagon/Core/HexagonGame.hpp b/include/SSVOpenHexagon/Core/HexagonGame.hpp index b2b10d0e..60260392 100644 --- a/include/SSVOpenHexagon/Core/HexagonGame.hpp +++ b/include/SSVOpenHexagon/Core/HexagonGame.hpp @@ -33,6 +33,8 @@ #include #include +#include + #include #include @@ -101,6 +103,9 @@ class HexagonGame TextUI(HGAssets& mAssets); }; + sf::GraphicsContext* graphicsContext; + sf::base::Optional nullTexture; + Steam::steam_manager* steamManager; Discord::discord_manager* discordManager; bool discordHung{false}; @@ -453,7 +458,8 @@ class HexagonGame public: std::function fnGoToMenu; - HexagonGame(Steam::steam_manager* mSteamManager, + HexagonGame(sf::GraphicsContext* graphicsContext, + Steam::steam_manager* mSteamManager, Discord::discord_manager* mDiscordManager, HGAssets& mAssets, Audio* mAudio, ssvs::GameWindow* mGameWindow, HexagonClient* mHexagonClient); diff --git a/include/SSVOpenHexagon/Core/MenuGame.hpp b/include/SSVOpenHexagon/Core/MenuGame.hpp index 345349e2..17489247 100644 --- a/include/SSVOpenHexagon/Core/MenuGame.hpp +++ b/include/SSVOpenHexagon/Core/MenuGame.hpp @@ -26,6 +26,8 @@ #include #include +#include + #include #include @@ -97,6 +99,7 @@ class MenuGame //--------------------------------------- // Classes + sf::GraphicsContext& graphicsContext; Steam::steam_manager& steamManager; Discord::discord_manager& discordManager; HGAssets& assets; @@ -572,7 +575,8 @@ class MenuGame const std::string& extra = ""); public: - MenuGame(Steam::steam_manager& mSteamManager, + MenuGame(sf::GraphicsContext& mGraphicsContext, + Steam::steam_manager& mSteamManager, Discord::discord_manager& mDiscordManager, HGAssets& mAssets, Audio& mAudio, ssvs::GameWindow& mGameWindow, HexagonClient& mHexagonClient); diff --git a/include/SSVOpenHexagon/Global/AssetStorage.hpp b/include/SSVOpenHexagon/Global/AssetStorage.hpp index 915ae09a..51416b26 100644 --- a/include/SSVOpenHexagon/Global/AssetStorage.hpp +++ b/include/SSVOpenHexagon/Global/AssetStorage.hpp @@ -4,15 +4,17 @@ #pragma once +#include "Imgui.hpp" #include "SSVOpenHexagon/Utils/UniquePtr.hpp" #include namespace sf { +class Font; +class GraphicsContext; class SoundBuffer; class Texture; -class Font; } // namespace sf @@ -32,10 +34,11 @@ class AssetStorage explicit AssetStorage(); ~AssetStorage(); - [[nodiscard]] bool loadTexture( + [[nodiscard]] bool loadTexture(sf::GraphicsContext& graphicsContext, const std::string& id, const std::string& path); - [[nodiscard]] bool loadFont(const std::string& id, const std::string& path); + [[nodiscard]] bool loadFont(sf::GraphicsContext& graphicsContext, + const std::string& id, const std::string& path); [[nodiscard]] bool loadSoundBuffer( const std::string& id, const std::string& path); diff --git a/include/SSVOpenHexagon/Global/Assets.hpp b/include/SSVOpenHexagon/Global/Assets.hpp index 284de79d..2bce6d8c 100644 --- a/include/SSVOpenHexagon/Global/Assets.hpp +++ b/include/SSVOpenHexagon/Global/Assets.hpp @@ -14,10 +14,11 @@ #include namespace sf { -class SoundBuffer; class Font; -class Texture; +class GraphicsContext; class Shader; +class SoundBuffer; +class Texture; } // namespace sf namespace ssvu::FileSystem { @@ -46,7 +47,8 @@ class HGAssets Utils::UniquePtr _impl; public: - HGAssets(Steam::steam_manager* mSteamManager, bool mHeadless, + HGAssets(sf::GraphicsContext* graphicsContext, + Steam::steam_manager* mSteamManager, bool mHeadless, bool mLevelsOnly = false); ~HGAssets(); @@ -55,8 +57,8 @@ class HGAssets [[nodiscard]] LoadInfo& getLoadResults(); + [[nodiscard]] bool hasTexture(const std::string& mId); [[nodiscard]] sf::Texture& getTexture(const std::string& mId); - [[nodiscard]] sf::Texture& getTextureOrNullTexture(const std::string& mId); [[nodiscard]] sf::Font& getFont(const std::string& mId); @@ -99,7 +101,7 @@ class HGAssets [[nodiscard]] sf::Shader* getShaderByShaderId(const std::size_t mShaderId); [[nodiscard]] bool isValidShaderId(const std::size_t mShaderId) const; - void reloadAllShaders(); + void reloadAllShaders(sf::GraphicsContext& graphicsContext); [[nodiscard]] std::string reloadPack( const std::string& mPackId, const std::string& mPath); [[nodiscard]] std::string reloadLevel(const std::string& mPackId, diff --git a/include/SSVOpenHexagon/Global/Imgui.hpp b/include/SSVOpenHexagon/Global/Imgui.hpp index 8be4c7eb..7a31ca93 100644 --- a/include/SSVOpenHexagon/Global/Imgui.hpp +++ b/include/SSVOpenHexagon/Global/Imgui.hpp @@ -6,6 +6,7 @@ namespace sf { class Event; +class GraphicsContext; class RenderTarget; class RenderWindow; class Window; @@ -13,7 +14,7 @@ class Window; namespace hg::Imgui { -[[nodiscard]] bool initialize(sf::RenderWindow&); +[[nodiscard]] bool initialize(sf::GraphicsContext&, sf::RenderWindow&); void shutdown(); [[nodiscard]] bool wantCaptureKeyboard(); [[nodiscard]] bool wantCaptureMouse(); diff --git a/src/SSVOpenHexagon/Core/Audio.cpp b/src/SSVOpenHexagon/Core/Audio.cpp index c8ffc14b..4b03a7b9 100644 --- a/src/SSVOpenHexagon/Core/Audio.cpp +++ b/src/SSVOpenHexagon/Core/Audio.cpp @@ -18,6 +18,8 @@ #include #include +#include + #include #include @@ -34,7 +36,7 @@ class Audio::AudioImpl // TODO (P2): remove these, roll own system ssvs::SoundPlayer _soundPlayer; - std::optional _music; + sf::base::Optional _music; float _musicVolume; std::string _lastLoadedMusicPath; @@ -75,7 +77,7 @@ class Audio::AudioImpl SSVOH_ASSERT(volume >= 0.f && volume <= 100.f); _musicVolume = volume; - if (_music.has_value()) + if (_music.hasValue()) { _music->setVolume(_musicVolume); } @@ -83,7 +85,7 @@ class Audio::AudioImpl void resumeMusic() { - if (_music.has_value()) + if (_music.hasValue()) { _music->setVolume(_musicVolume); _music->play(_playbackDevice); @@ -92,7 +94,7 @@ class Audio::AudioImpl void pauseMusic() { - if (_music.has_value()) + if (_music.hasValue()) { _music->pause(); } @@ -100,7 +102,7 @@ class Audio::AudioImpl void stopMusic() { - if (_music.has_value()) + if (_music.hasValue()) { _music->stop(); } @@ -108,7 +110,7 @@ class Audio::AudioImpl void setMusicPlayingOffsetSeconds(const float seconds) { - if (_music.has_value()) + if (_music.hasValue()) { _music->setPlayingOffset(sf::seconds(seconds)); } @@ -116,7 +118,7 @@ class Audio::AudioImpl void setMusicPlayingOffsetMilliseconds(const int milliseconds) { - if (_music.has_value()) + if (_music.hasValue()) { _music->setPlayingOffset(sf::milliseconds(milliseconds)); } @@ -124,7 +126,7 @@ class Audio::AudioImpl [[nodiscard]] float getMusicPlayingOffsetSeconds() const { - if (_music.has_value()) + if (_music.hasValue()) { return _music->getPlayingOffset().asSeconds(); } @@ -134,7 +136,7 @@ class Audio::AudioImpl [[nodiscard]] int getMusicPlayingOffsetMilliseconds() const { - if (_music.has_value()) + if (_music.hasValue()) { return _music->getPlayingOffset().asMilliseconds(); } @@ -197,7 +199,7 @@ class Audio::AudioImpl _lastLoadedMusicPath = *path; } - SSVOH_ASSERT(_music.has_value()); + SSVOH_ASSERT(_music.hasValue()); _music->setLoop(true); setMusicPlayingOffsetSeconds(playingOffsetSeconds); @@ -208,7 +210,7 @@ class Audio::AudioImpl void setCurrentMusicPitch(const float pitch) { - if (_music.has_value()) + if (_music.hasValue()) { _music->setPitch(pitch); } diff --git a/src/SSVOpenHexagon/Core/HGGraphics.cpp b/src/SSVOpenHexagon/Core/HGGraphics.cpp index 903ed1e0..50b149ac 100644 --- a/src/SSVOpenHexagon/Core/HGGraphics.cpp +++ b/src/SSVOpenHexagon/Core/HGGraphics.cpp @@ -306,7 +306,8 @@ void HexagonGame::draw() { if (window != nullptr) { - window->saveScreenshot("screenshot.png"); + SSVOH_ASSERT(graphicsContext != nullptr); + window->saveScreenshot(*graphicsContext, "screenshot.png"); } mustTakeScreenshot = false; diff --git a/src/SSVOpenHexagon/Core/HGScripting.cpp b/src/SSVOpenHexagon/Core/HGScripting.cpp index a686c58e..b9174af7 100644 --- a/src/SSVOpenHexagon/Core/HGScripting.cpp +++ b/src/SSVOpenHexagon/Core/HGScripting.cpp @@ -30,8 +30,8 @@ #include -#include -#include +#include +#include #include #include diff --git a/src/SSVOpenHexagon/Core/HGUpdate.cpp b/src/SSVOpenHexagon/Core/HGUpdate.cpp index 7d285cca..70d68f9b 100644 --- a/src/SSVOpenHexagon/Core/HGUpdate.cpp +++ b/src/SSVOpenHexagon/Core/HGUpdate.cpp @@ -1000,7 +1000,7 @@ void HexagonGame::updateTrailParticles(float mFT) TrailParticle p{sf::Sprite{txSmallCircle->getRect()}}; p.sprite.setPosition(player.getPosition()); - p.sprite.setOrigin(sf::Vector2f{txSmallCircle->getSize()} / 2.f); + p.sprite.setOrigin(txSmallCircle->getSize().to() / 2.f); const float scale = Config::getPlayerTrailScale(); p.sprite.setScale({scale, scale}); @@ -1030,7 +1030,7 @@ void HexagonGame::updateTrailParticles(float mFT) p.sprite.setScale(p.sprite.getScale() * 0.98f); p.sprite.setPosition( - sf::Vector2f(status.radius + 2.4f, sf::radians(p.angle))); + sf::Vector2f::fromAngle(status.radius + 2.4f, sf::radians(p.angle))); } if (player.hasChangedAngle()) @@ -1054,7 +1054,7 @@ void HexagonGame::updateSwapParticles(float mFT) SwapParticle p{sf::Sprite(txSmallCircle->getRect())}; p.sprite.setPosition(si.position); - p.sprite.setOrigin(sf::Vector2f{txSmallCircle->getSize()} / 2.f); + p.sprite.setOrigin(txSmallCircle->getSize().to() / 2.f); const float scale = ssvu::getRndR(0.65f, 1.35f) * scaleMult; p.sprite.setScale({scale, scale}); @@ -1064,7 +1064,7 @@ void HexagonGame::updateSwapParticles(float mFT) c.a = alpha; p.sprite.setColor(c); - p.velocity = sf::Vector2f(ssvu::getRndR(0.1f, 10.f) * speedMult, + p.velocity = sf::Vector2f::fromAngle(ssvu::getRndR(0.1f, 10.f) * speedMult, sf::radians(si.angle + ssvu::getRndR(-expand, expand))); return p; diff --git a/src/SSVOpenHexagon/Core/HexagonGame.cpp b/src/SSVOpenHexagon/Core/HexagonGame.cpp index 00f28ed4..f6cd4b9c 100644 --- a/src/SSVOpenHexagon/Core/HexagonGame.cpp +++ b/src/SSVOpenHexagon/Core/HexagonGame.cpp @@ -35,7 +35,12 @@ #include -#include +#include +#include + +#include +#include +#include #include @@ -80,6 +85,18 @@ void HexagonGame::setMustStart(const bool x) mustStart = x; } +static sf::Texture& getTextureOrNullTexture(HGAssets& assets, + sf::base::Optional& nullTexture, const std::string& mId) +{ + if (!assets.hasTexture(mId)) + { + SSVOH_ASSERT(nullTexture.hasValue()); + return *nullTexture; + } + + return assets.getTexture(mId); +} + void HexagonGame::initKeyIcons() { if (window == nullptr) @@ -90,7 +107,8 @@ void HexagonGame::initKeyIcons() for (const auto& t : {"keyArrow.png", "keyFocus.png", "keySwap.png", "replayIcon.png"}) { - assets.getTextureOrNullTexture(t).setSmooth(true); + SSVOH_ASSERT(graphicsContext != nullptr); + getTextureOrNullTexture(assets, nullTexture, t).setSmooth(true); } updateKeyIcons(); @@ -302,10 +320,15 @@ HexagonGame::TextUI::TextUI(HGAssets& mAssets) replayText{initText(font, "", 20.f)} {} -HexagonGame::HexagonGame(Steam::steam_manager* mSteamManager, +HexagonGame::HexagonGame(sf::GraphicsContext* mGraphicsContext, + Steam::steam_manager* mSteamManager, Discord::discord_manager* mDiscordManager, HGAssets& mAssets, Audio* mAudio, ssvs::GameWindow* mGameWindow, HexagonClient* mHexagonClient) - : steamManager(mSteamManager), + : graphicsContext(mGraphicsContext), + nullTexture(graphicsContext != nullptr + ? sf::Texture::create(*graphicsContext, {1u, 1u}) + : sf::base::nullOpt), + steamManager(mSteamManager), discordManager(mDiscordManager), assets(mAssets), audio(mAudio), @@ -345,14 +368,23 @@ HexagonGame::HexagonGame(Steam::steam_manager* mSteamManager, overlayCamera.emplace(sf::View{sf::Vector2f{width / 2.f, height / 2.f}, sf::Vector2f{width, height}}); - txStarParticle = &assets.getTextureOrNullTexture("starParticle.png"); - txSmallCircle = &assets.getTextureOrNullTexture("smallCircle.png"); - - txKeyIconLeft = &assets.getTextureOrNullTexture("keyArrow.png"); - txKeyIconRight = &assets.getTextureOrNullTexture("keyArrow.png"); - txKeyIconFocus = &assets.getTextureOrNullTexture("keyFocus.png"); - txKeyIconSwap = &assets.getTextureOrNullTexture("keySwap.png"); - txReplayIcon = &assets.getTextureOrNullTexture("replayIcon.png"); + SSVOH_ASSERT(graphicsContext != nullptr); + + txStarParticle = + &getTextureOrNullTexture(assets, nullTexture, "starParticle.png"); + txSmallCircle = + &getTextureOrNullTexture(assets, nullTexture, "smallCircle.png"); + + txKeyIconLeft = + &getTextureOrNullTexture(assets, nullTexture, "keyArrow.png"); + txKeyIconRight = + &getTextureOrNullTexture(assets, nullTexture, "keyArrow.png"); + txKeyIconFocus = + &getTextureOrNullTexture(assets, nullTexture, "keyFocus.png"); + txKeyIconSwap = + &getTextureOrNullTexture(assets, nullTexture, "keySwap.png"); + txReplayIcon = + &getTextureOrNullTexture(assets, nullTexture, "replayIcon.png"); keyIconLeft.setTextureRect(txKeyIconLeft->getRect()); keyIconRight.setTextureRect(txKeyIconRight->getRect()); diff --git a/src/SSVOpenHexagon/Core/HexagonServer.cpp b/src/SSVOpenHexagon/Core/HexagonServer.cpp index e29e8c34..54409944 100644 --- a/src/SSVOpenHexagon/Core/HexagonServer.cpp +++ b/src/SSVOpenHexagon/Core/HexagonServer.cpp @@ -30,6 +30,8 @@ #include +#include + #include #include @@ -320,7 +322,7 @@ bool HexagonServer::runIteration_Control() return fail(); } - std::optional senderIp; + sf::base::Optional senderIp; unsigned short senderPort; if (_controlSocket.receive(_packetBuffer, senderIp, senderPort) != @@ -336,7 +338,7 @@ bool HexagonServer::runIteration_Control() return fail("Failure decoding control packet"); } - SSVOH_ASSERT(senderIp.has_value()); + SSVOH_ASSERT(senderIp.hasValue()); SSVOH_SLOG << "Received control packet from '" << senderIp.value() << ':' << senderPort << "', contents: '" << controlMsg << "'\n"; diff --git a/src/SSVOpenHexagon/Core/LuaScripting.cpp b/src/SSVOpenHexagon/Core/LuaScripting.cpp index cd03df7f..596e815b 100644 --- a/src/SSVOpenHexagon/Core/LuaScripting.cpp +++ b/src/SSVOpenHexagon/Core/LuaScripting.cpp @@ -1379,7 +1379,7 @@ static void initShaders(Lua::LuaContext& lua, HGAssets& assets, const auto location = shader.getUniformLocation(name) .value(); // TODO: optimization opportunity - shader.setUniformUnsafe(location, a); + shader.setUniform(location, a); }); }) .arg("shaderId") @@ -1399,7 +1399,7 @@ static void initShaders(Lua::LuaContext& lua, HGAssets& assets, const auto location = shader.getUniformLocation(name) .value(); // TODO: optimization opportunity - shader.setUniformUnsafe(location, sf::Glsl::Vec2{a, b}); + shader.setUniform(location, sf::Glsl::Vec2{a, b}); }); }) .arg("shaderId") @@ -1420,7 +1420,7 @@ static void initShaders(Lua::LuaContext& lua, HGAssets& assets, const auto location = shader.getUniformLocation(name) .value(); // TODO: optimization opportunity - shader.setUniformUnsafe(location, sf::Glsl::Vec3{a, b, c}); + shader.setUniform(location, sf::Glsl::Vec3{a, b, c}); }); }) .arg("shaderId") @@ -1442,7 +1442,7 @@ static void initShaders(Lua::LuaContext& lua, HGAssets& assets, const auto location = shader.getUniformLocation(name) .value(); // TODO: optimization opportunity - shader.setUniformUnsafe( + shader.setUniform( location, sf::Glsl::Vec4{a, b, c, d}); }); }) @@ -1469,7 +1469,7 @@ static void initShaders(Lua::LuaContext& lua, HGAssets& assets, const auto location = shader.getUniformLocation(name) .value(); // TODO: optimization opportunity - shader.setUniformUnsafe(location, a); + shader.setUniform(location, a); }); }) .arg("shaderId") @@ -1489,7 +1489,7 @@ static void initShaders(Lua::LuaContext& lua, HGAssets& assets, const auto location = shader.getUniformLocation(name) .value(); // TODO: optimization opportunity - shader.setUniformUnsafe(location, sf::Glsl::Ivec2{a, b}); + shader.setUniform(location, sf::Glsl::Ivec2{a, b}); }); }) .arg("shaderId") @@ -1510,7 +1510,7 @@ static void initShaders(Lua::LuaContext& lua, HGAssets& assets, const auto location = shader.getUniformLocation(name) .value(); // TODO: optimization opportunity - shader.setUniformUnsafe(location, sf::Glsl::Ivec3{a, b, c}); + shader.setUniform(location, sf::Glsl::Ivec3{a, b, c}); }); }) .arg("shaderId") @@ -1532,7 +1532,7 @@ static void initShaders(Lua::LuaContext& lua, HGAssets& assets, const auto location = shader.getUniformLocation(name) .value(); // TODO: optimization opportunity - shader.setUniformUnsafe( + shader.setUniform( location, sf::Glsl::Ivec4{a, b, c, d}); }); }) diff --git a/src/SSVOpenHexagon/Core/MenuGame.cpp b/src/SSVOpenHexagon/Core/MenuGame.cpp index a1ffa4f9..91b80838 100644 --- a/src/SSVOpenHexagon/Core/MenuGame.cpp +++ b/src/SSVOpenHexagon/Core/MenuGame.cpp @@ -148,10 +148,12 @@ void MenuGame::initOnlineIcons() inline constexpr float maxOffset{100.f}; -MenuGame::MenuGame(Steam::steam_manager& mSteamManager, +MenuGame::MenuGame(sf::GraphicsContext& mGraphicsContext, + Steam::steam_manager& mSteamManager, Discord::discord_manager& mDiscordManager, HGAssets& mAssets, Audio& mAudio, ssvs::GameWindow& mGameWindow, HexagonClient& mHexagonClient) - : steamManager(mSteamManager), + : graphicsContext(mGraphicsContext), + steamManager(mSteamManager), discordManager(mDiscordManager), assets(mAssets), openSquare(mAssets.getFont("OpenSquare-Regular.ttf")), @@ -3089,7 +3091,7 @@ void MenuGame::reloadAssets(const bool reloadEntirePack) return; } - assets.reloadAllShaders(); + assets.reloadAllShaders(graphicsContext); // Do the necessary asset reload operation and get the log // of the results. @@ -5953,7 +5955,7 @@ void MenuGame::draw() if (mustTakeScreenshot) { - window.saveScreenshot("screenshot.png"); + window.saveScreenshot(graphicsContext, "screenshot.png"); mustTakeScreenshot = false; } diff --git a/src/SSVOpenHexagon/Core/main.cpp b/src/SSVOpenHexagon/Core/main.cpp index 81d42b36..b9e1c6d3 100644 --- a/src/SSVOpenHexagon/Core/main.cpp +++ b/src/SSVOpenHexagon/Core/main.cpp @@ -34,6 +34,10 @@ #include #include +#include + +#include + #include #include #include @@ -167,17 +171,19 @@ getFirstCompressedReplayFilenameFromArgs(const std::vector& args) [[nodiscard]] int mainPrintLuaDocs() { hg::HGAssets assets{ - nullptr, /* steamManager */ // - true /* headless */ // + nullptr, /* graphicsContext */ // + nullptr, /* steamManager */ // + true /* headless */ // }; hg::HexagonGame hg{ - nullptr /* steamManager */, // - nullptr /* discordManager */, // - assets, // - nullptr /* audio */, // - nullptr /* window */, // - nullptr /* client */ // + nullptr, /* graphicsContext */ // + nullptr, /* steamManager */ // + nullptr, /* discordManager */ // + assets, // + nullptr, /* audio */ // + nullptr, /* window */ // + nullptr /* client */ // }; std::cout << "\n\n\n\n\n"; @@ -208,17 +214,19 @@ getFirstCompressedReplayFilenameFromArgs(const std::vector& args) }); hg::HGAssets assets{ - &steamManager, // - true /* headless */ // + nullptr, /* graphicsContext */ // + &steamManager, // + true /* headless */ // }; hg::HexagonGame hg{ - nullptr /* steamManager */, // - nullptr /* discordManager */, // - assets, // - nullptr /* audio */, // - nullptr /* window */, // - nullptr /* client */ // + nullptr, /* graphicsContext */ // + nullptr /* steamManager */, // + nullptr /* discordManager */, // + assets, // + nullptr /* audio */, // + nullptr /* window */, // + nullptr /* client */ // }; // TODO (P0): handle `resolve` errors @@ -294,11 +302,12 @@ getFirstCompressedReplayFilenameFromArgs(const std::vector& args) // // ------------------------------------------------------------------------ // Create the game window + sf::GraphicsContext graphicsContext; std::optional window; if (!headless) { - window.emplace(); + window.emplace(graphicsContext); window->setTitle(makeWindowTitle()); window->setSize(hg::Config::getWidth(), hg::Config::getHeight()); @@ -312,10 +321,10 @@ getFirstCompressedReplayFilenameFromArgs(const std::vector& args) { const auto resetIcon = [&window] { - const std::optional icon = + const sf::base::Optional icon = sf::Image::loadFromFile("Assets/icon.png"); - if (!icon.has_value()) + if (!icon.hasValue()) { ssvu::lo("::main") << "Failed to load icon image\n"; return; @@ -360,7 +369,7 @@ getFirstCompressedReplayFilenameFromArgs(const std::vector& args) if (!headless) { SSVOH_ASSERT(window.has_value()); - if (!hg::Imgui::initialize(*window)) + if (!hg::Imgui::initialize(graphicsContext, *window)) { ssvu::lo("::main") << "Failed to initialize ImGui...\n"; } @@ -381,7 +390,7 @@ getFirstCompressedReplayFilenameFromArgs(const std::vector& args) // // ------------------------------------------------------------------------ // Initialize assets - hg::HGAssets assets{&steamManager, headless}; + hg::HGAssets assets{&graphicsContext, &steamManager, headless}; HG_SCOPE_GUARD({ ssvu::lo("::main") << "Saving all local profiles...\n"; assets.pSaveAll(); @@ -420,6 +429,7 @@ getFirstCompressedReplayFilenameFromArgs(const std::vector& args) // ------------------------------------------------------------------------ // Initialize hexagon game hg::HexagonGame hg{ + &graphicsContext, &steamManager, // (discordManager.has_value() ? &*discordManager : nullptr), // assets, // @@ -439,7 +449,8 @@ getFirstCompressedReplayFilenameFromArgs(const std::vector& args) SSVOH_ASSERT(window.has_value()); SSVOH_ASSERT(discordManager.has_value()); - mg.emplace(steamManager, *discordManager, assets, audio, *window, hc); + mg.emplace(graphicsContext, steamManager, *discordManager, assets, + audio, *window, hc); mg->fnHGTriggerRefresh = [&](const ssvs::Input::Trigger& trigger, int bindId) // @@ -596,7 +607,7 @@ getFirstCompressedReplayFilenameFromArgs(const std::vector& args) if (!headless) { SSVOH_ASSERT(window.has_value()); - window->run(); + window->run(graphicsContext); } ssvu::lo("::mainClient") << "Finished\n"; diff --git a/src/SSVOpenHexagon/Global/AssetStorage.cpp b/src/SSVOpenHexagon/Global/AssetStorage.cpp index 4043bc36..c254e828 100644 --- a/src/SSVOpenHexagon/Global/AssetStorage.cpp +++ b/src/SSVOpenHexagon/Global/AssetStorage.cpp @@ -6,6 +6,7 @@ #include "SSVOpenHexagon/Global/Assert.hpp" +#include "SSVOpenHexagon/Global/Imgui.hpp" #include "SSVOpenHexagon/Global/Macros.hpp" #include "SSVOpenHexagon/Utils/UniquePtr.hpp" @@ -15,6 +16,10 @@ #include +#include + +#include + #include #include @@ -35,12 +40,12 @@ class AssetStorage::AssetStorageImpl std::unordered_map _soundBuffers; public: - [[nodiscard]] bool loadTexture( + [[nodiscard]] bool loadTexture(sf::GraphicsContext& graphicsContext, const std::string& id, const std::string& path) { - std::optional texture = sf::Texture::loadFromFile(path); + sf::base::Optional texture = sf::Texture::loadFromFile(graphicsContext, path); - if (!texture.has_value()) + if (!texture.hasValue()) { return false; } @@ -49,11 +54,12 @@ class AssetStorage::AssetStorageImpl return inserted; } - [[nodiscard]] bool loadFont(const std::string& id, const std::string& path) + [[nodiscard]] bool loadFont(sf::GraphicsContext& graphicsContext, + const std::string& id, const std::string& path) { - std::optional font = sf::Font::openFromFile(path); + sf::base::Optional font = sf::Font::openFromFile(graphicsContext, path); - if (!font.has_value()) + if (!font.hasValue()) { return false; } @@ -65,9 +71,9 @@ class AssetStorage::AssetStorageImpl [[nodiscard]] bool loadSoundBuffer( const std::string& id, const std::string& path) { - std::optional soundBuffer = sf::SoundBuffer::loadFromFile(path); + sf::base::Optional soundBuffer = sf::SoundBuffer::loadFromFile(path); - if (!soundBuffer.has_value()) + if (!soundBuffer.hasValue()) { return false; } @@ -128,15 +134,16 @@ AssetStorage::AssetStorage() : _impl{Utils::makeUnique()} AssetStorage::~AssetStorage() = default; [[nodiscard]] bool AssetStorage::loadTexture( - const std::string& id, const std::string& path) + sf::GraphicsContext& graphicsContext, const std::string& id, + const std::string& path) { - return impl().loadTexture(id, path); + return impl().loadTexture(graphicsContext, id, path); } -[[nodiscard]] bool AssetStorage::loadFont( +[[nodiscard]] bool AssetStorage::loadFont(sf::GraphicsContext& graphicsContext, const std::string& id, const std::string& path) { - return impl().loadFont(id, path); + return impl().loadFont(graphicsContext, id, path); } [[nodiscard]] bool AssetStorage::loadSoundBuffer( diff --git a/src/SSVOpenHexagon/Global/Assets.cpp b/src/SSVOpenHexagon/Global/Assets.cpp index 88b3fb1a..96c1522d 100644 --- a/src/SSVOpenHexagon/Global/Assets.cpp +++ b/src/SSVOpenHexagon/Global/Assets.cpp @@ -98,18 +98,20 @@ class HGAssets::HGAssetsImpl [[nodiscard]] std::string& concatIntoBuf(const Ts&...); [[nodiscard]] bool loadAllPackDatas(); - [[nodiscard]] bool loadAllPackAssets(const bool headless); + [[nodiscard]] bool loadAllPackAssets( + sf::GraphicsContext* graphicsContext, const bool headless); [[nodiscard]] bool loadWorkshopPackDatasFromCache(); [[nodiscard]] bool verifyAllPackDependencies(); [[nodiscard]] bool loadAllLocalProfiles(); [[nodiscard]] bool loadPackData(const ssvufs::Path& packPath); - [[nodiscard]] bool loadPackAssets( + [[nodiscard]] bool loadPackAssets(sf::GraphicsContext* graphicsContext, const PackData& packData, const bool headless); - void loadPackAssets_loadShaders(const std::string& mPackId, - const ssvufs::Path& mPath, const bool headless); + void loadPackAssets_loadShaders(sf::GraphicsContext& graphicsContext, + const std::string& mPackId, const ssvufs::Path& mPath, + const bool headless); void loadPackAssets_loadMusic( const std::string& mPackId, const ssvufs::Path& mPath); void loadPackAssets_loadMusicData( @@ -124,7 +126,8 @@ class HGAssets::HGAssetsImpl [[nodiscard]] std::string getCurrentLocalProfileFilePath(); public: - HGAssetsImpl(Steam::steam_manager* mSteamManager, bool mHeadless, + HGAssetsImpl(sf::GraphicsContext* graphicsContext, + Steam::steam_manager* mSteamManager, bool mHeadless, bool mLevelsOnly = false); ~HGAssetsImpl(); @@ -133,8 +136,8 @@ class HGAssets::HGAssetsImpl [[nodiscard]] LoadInfo& getLoadResults(); + [[nodiscard]] bool hasTexture(const std::string& mId); [[nodiscard]] sf::Texture& getTexture(const std::string& mId); - [[nodiscard]] sf::Texture& getTextureOrNullTexture(const std::string& mId); [[nodiscard]] sf::Font& getFont(const std::string& mId); @@ -177,7 +180,7 @@ class HGAssets::HGAssetsImpl [[nodiscard]] sf::Shader* getShaderByShaderId(const std::size_t mShaderId); [[nodiscard]] bool isValidShaderId(const std::size_t mShaderId) const; - void reloadAllShaders(); + void reloadAllShaders(sf::GraphicsContext& graphicsContext); [[nodiscard]] std::string reloadPack( const std::string& mPackId, const std::string& mPath); [[nodiscard]] std::string reloadLevel(const std::string& mPackId, @@ -227,13 +230,14 @@ class HGAssets::HGAssetsImpl getLuaFileCache() const; }; -static void loadAssetsFromJson(AssetStorage& assetStorage, - const ssvu::FileSystem::Path& mRootPath, const ssvuj::Obj& mObj) +static void loadAssetsFromJson(sf::GraphicsContext& graphicsContext, + AssetStorage& assetStorage, const ssvu::FileSystem::Path& mRootPath, + const ssvuj::Obj& mObj) { for (const auto& f : ssvuj::getExtr>(mObj, "fonts")) { - if (!assetStorage.loadFont(f, mRootPath + f)) + if (!assetStorage.loadFont(graphicsContext, f, mRootPath + f)) { ssvu::lo("hg::loadAssetsFromJson") << "Failed to load font '" << f << "'\n"; @@ -243,7 +247,7 @@ static void loadAssetsFromJson(AssetStorage& assetStorage, for (const auto& f : ssvuj::getExtr>(mObj, "textures")) { - if (!assetStorage.loadTexture(f, mRootPath + f)) + if (!assetStorage.loadTexture(graphicsContext, f, mRootPath + f)) { ssvu::lo("hg::loadAssetsFromJson") << "Failed to load texture '" << f << "'\n"; @@ -311,7 +315,7 @@ template return buf; } -HGAssets::HGAssetsImpl::HGAssetsImpl( +HGAssets::HGAssetsImpl::HGAssetsImpl(sf::GraphicsContext* graphicsContext, Steam::steam_manager* mSteamManager, bool mHeadless, bool mLevelsOnly) : steamManager{mSteamManager}, _headless{mHeadless}, @@ -334,7 +338,8 @@ HGAssets::HGAssetsImpl::HGAssetsImpl( auto [object, error] = ssvuj::getFromFileWithErrors("Assets/assets.json"); - loadAssetsFromJson(*assetStorage, "Assets/", object); + SSVOH_ASSERT(graphicsContext != nullptr); + loadAssetsFromJson(*graphicsContext, *assetStorage, "Assets/", object); loadInfo.addFormattedError(error); } @@ -346,7 +351,7 @@ HGAssets::HGAssetsImpl::HGAssetsImpl( return; } - if (!loadAllPackAssets(mHeadless)) + if (!loadAllPackAssets(graphicsContext, mHeadless)) { ssvu::lo("HGAssets::HGAssets") << "Error loading all pack assets\n"; std::terminate(); @@ -496,7 +501,8 @@ HGAssets::HGAssetsImpl::~HGAssetsImpl() } [[nodiscard]] bool HGAssets::HGAssetsImpl::loadPackAssets( - const PackData& packData, const bool headless) + sf::GraphicsContext* graphicsContext, const PackData& packData, + const bool headless) { const std::string& packPath{packData.folderPath}; const std::string& packId{packData.id}; @@ -509,7 +515,10 @@ HGAssets::HGAssetsImpl::~HGAssetsImpl() { if (ssvufs::Path{packPath + "Shaders/"}.isFolder() && !levelsOnly) { - loadPackAssets_loadShaders(packId, packPath, headless); + SSVOH_ASSERT(graphicsContext != nullptr); + + loadPackAssets_loadShaders( + *graphicsContext, packId, packPath, headless); } if (!levelsOnly && ssvufs::Path{packPath + "Sounds/"}.isFolder()) @@ -573,23 +582,19 @@ HGAssets::HGAssetsImpl::~HGAssetsImpl() return loadInfo; } -[[nodiscard]] sf::Texture& HGAssets::HGAssetsImpl::getTexture( - const std::string& mId) +[[nodiscard]] bool HGAssets::HGAssetsImpl::hasTexture(const std::string& mId) { sf::Texture* ptr = assetStorage->getTexture(mId); - SSVOH_ASSERT(ptr); - - return *ptr; + return ptr != nullptr; } -[[nodiscard]] sf::Texture& HGAssets::HGAssetsImpl::getTextureOrNullTexture( +[[nodiscard]] sf::Texture& HGAssets::HGAssetsImpl::getTexture( const std::string& mId) { - static auto nullTexture = sf::Texture::create({1u, 1u}); - SSVOH_ASSERT(nullTexture.has_value()); - sf::Texture* ptr = assetStorage->getTexture(mId); - return ptr ? *ptr : *nullTexture; + SSVOH_ASSERT(ptr); + + return *ptr; } [[nodiscard]] sf::Font& HGAssets::HGAssetsImpl::getFont(const std::string& mId) @@ -780,11 +785,11 @@ HGAssets::HGAssetsImpl::getSelectablePackInfos() const noexcept } [[nodiscard]] bool HGAssets::HGAssetsImpl::loadAllPackAssets( - const bool headless) + sf::GraphicsContext* graphicsContext, const bool headless) { for (const auto& [packId, packData] : packDatas) { - if (loadPackAssets(packData, headless)) + if (loadPackAssets(graphicsContext, packData, headless)) { continue; } @@ -883,7 +888,8 @@ void HGAssets::HGAssetsImpl::addLocalProfile(ProfileData&& profileData) } void HGAssets::HGAssetsImpl::loadPackAssets_loadShaders( - const std::string& mPackId, const ssvufs::Path& mPath, const bool headless) + sf::GraphicsContext& graphicsContext, const std::string& mPackId, + const ssvufs::Path& mPath, const bool headless) { if (headless) { @@ -896,10 +902,10 @@ void HGAssets::HGAssetsImpl::loadPackAssets_loadShaders( { for (const auto& p : scanSingleByExt(mPath + "Shaders/", extension)) { - std::optional shader = - sf::Shader::loadFromFile(p.getStr(), shaderType); + sf::base::Optional shader = sf::Shader::loadFromFile( + graphicsContext, p.getStr(), shaderType); - if (!shader.has_value()) + if (!shader.hasValue()) { ssvu::lo("hg::loadPackAssets_loadShaders") << "Failed to load shader '" << p << "'\n"; @@ -1172,18 +1178,23 @@ HGAssets::HGAssetsImpl::getShaderIdByPath(const std::string& mShaderPath) //********************************************** // RELOAD -void HGAssets::HGAssetsImpl::reloadAllShaders() +void HGAssets::HGAssetsImpl::reloadAllShaders( + sf::GraphicsContext& graphicsContext) { for (auto& [id, loadedShader] : shaders) { - if (!loadedShader.shader->loadFromFile( - loadedShader.path, loadedShader.shaderType)) + auto reloadedShader = sf::Shader::loadFromFile( + graphicsContext, loadedShader.path, loadedShader.shaderType); + + if (!reloadedShader.hasValue()) { ssvu::lo("hg::HGAssetsImplImpl::reloadAllShaders") << "Failed to load shader '" << loadedShader.path << "'\n"; continue; } + + (*loadedShader.shader) = *SSVOH_MOVE(reloadedShader); } } @@ -1622,10 +1633,10 @@ HGAssets::HGAssetsImpl::getLuaFileCache() const // ---------------------------------------------------------------------------- -HGAssets::HGAssets( +HGAssets::HGAssets(sf::GraphicsContext* graphicsContext, Steam::steam_manager* mSteamManager, bool mHeadless, bool mLevelsOnly) : _impl(Utils::makeUnique( - mSteamManager, mHeadless, mLevelsOnly)) + graphicsContext, mSteamManager, mHeadless, mLevelsOnly)) {} HGAssets::~HGAssets() = default; @@ -1635,14 +1646,14 @@ LoadInfo& HGAssets::getLoadResults() return _impl->getLoadResults(); } -sf::Texture& HGAssets::getTexture(const std::string& mId) +bool HGAssets::hasTexture(const std::string& mId) { - return _impl->getTexture(mId); + return _impl->hasTexture(mId); } -sf::Texture& HGAssets::getTextureOrNullTexture(const std::string& mId) +sf::Texture& HGAssets::getTexture(const std::string& mId) { - return _impl->getTextureOrNullTexture(mId); + return _impl->getTexture(mId); } sf::Font& HGAssets::getFont(const std::string& mId) @@ -1737,9 +1748,9 @@ bool HGAssets::isValidShaderId(const std::size_t mShaderId) const return _impl->isValidShaderId(mShaderId); } -void HGAssets::reloadAllShaders() +void HGAssets::reloadAllShaders(sf::GraphicsContext& graphicsContext) { - return _impl->reloadAllShaders(); + return _impl->reloadAllShaders(graphicsContext); } std::string HGAssets::reloadPack( diff --git a/src/SSVOpenHexagon/Global/Imgui.cpp b/src/SSVOpenHexagon/Global/Imgui.cpp index e0115009..8b0053de 100644 --- a/src/SSVOpenHexagon/Global/Imgui.cpp +++ b/src/SSVOpenHexagon/Global/Imgui.cpp @@ -10,15 +10,20 @@ #include #endif -#include -#include +#include + +#include +#include +#include namespace hg::Imgui { -[[nodiscard]] bool initialize([[maybe_unused]] sf::RenderWindow& window) +[[nodiscard]] bool initialize( + [[maybe_unused]] sf::GraphicsContext& graphicsContext, + [[maybe_unused]] sf::RenderWindow& window) { #ifndef SSVOH_ANDROID - return ImGui::SFML::Init(window); + return ImGui::SFML::Init(graphicsContext, window); #endif }