From ec01bc79860c55fe3562dafb4b4cb0aa2ce50a21 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Sun, 3 Mar 2024 19:52:26 -0500 Subject: [PATCH] Font as resource (#454) --- src/CMakeLists.txt | 4 +++ src/resource/ResourceManager.cpp | 40 ++++++++++--------------- src/resource/ResourceManager.h | 16 +++++----- src/resource/archive/Archive.cpp | 28 ++++++++++------- src/resource/archive/Archive.h | 5 ++-- src/resource/archive/ArchiveManager.cpp | 9 +++--- src/resource/archive/ArchiveManager.h | 5 ++-- src/window/gui/GameOverlay.cpp | 19 ++++++++---- src/window/gui/resource/Font.cpp | 20 +++++++++++++ src/window/gui/resource/Font.h | 21 +++++++++++++ src/window/gui/resource/FontFactory.cpp | 25 ++++++++++++++++ src/window/gui/resource/FontFactory.h | 11 +++++++ 12 files changed, 147 insertions(+), 56 deletions(-) create mode 100644 src/window/gui/resource/Font.cpp create mode 100644 src/window/gui/resource/Font.h create mode 100644 src/window/gui/resource/FontFactory.cpp create mode 100644 src/window/gui/resource/FontFactory.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6e565613c..af2bba262 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -247,6 +247,10 @@ set(Source_Files__Window__Gui ${CMAKE_CURRENT_SOURCE_DIR}/window/gui/GuiElement.cpp ${CMAKE_CURRENT_SOURCE_DIR}/window/gui/GuiMenuBar.h ${CMAKE_CURRENT_SOURCE_DIR}/window/gui/GuiMenuBar.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/window/gui/resource/Font.h + ${CMAKE_CURRENT_SOURCE_DIR}/window/gui/resource/Font.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/window/gui/resource/FontFactory.h + ${CMAKE_CURRENT_SOURCE_DIR}/window/gui/resource/FontFactory.cpp ) source_group("window/gui" FILES ${Source_Files__Window__Gui}) diff --git a/src/resource/ResourceManager.cpp b/src/resource/ResourceManager.cpp index e6dd0e11f..e78a2af0a 100644 --- a/src/resource/ResourceManager.cpp +++ b/src/resource/ResourceManager.cpp @@ -45,8 +45,9 @@ bool ResourceManager::DidLoadSuccessfully() { return mArchiveManager != nullptr && mArchiveManager->IsArchiveLoaded(); } -std::shared_ptr ResourceManager::LoadFileProcess(const std::string& filePath) { - auto file = mArchiveManager->LoadFile(filePath); +std::shared_ptr ResourceManager::LoadFileProcess(const std::string& filePath, + std::shared_ptr initData) { + auto file = mArchiveManager->LoadFile(filePath, initData); if (file != nullptr) { SPDLOG_TRACE("Loaded File {} on ResourceManager", file->InitData->Path); } else { @@ -55,18 +56,19 @@ std::shared_ptr ResourceManager::LoadFileProcess(const std::string& filePa return file; } -std::shared_ptr ResourceManager::LoadResourceProcess(const std::string& filePath, bool loadExact) { +std::shared_ptr ResourceManager::LoadResourceProcess(const std::string& filePath, bool loadExact, + std::shared_ptr initData) { // Check for and remove the OTR signature if (OtrSignatureCheck(filePath.c_str())) { const auto newFilePath = filePath.substr(7); - return LoadResourceProcess(newFilePath); + return LoadResourceProcess(newFilePath, false, initData); } // Attempt to load the alternate version of the asset, if we fail then we continue trying to load the standard // asset. if (!loadExact && CVarGetInteger("gAltAssets", 0) && !filePath.starts_with(IResource::gAltAssetPrefix)) { const auto altPath = IResource::gAltAssetPrefix + filePath; - auto altResource = LoadResourceProcess(altPath, loadExact); + auto altResource = LoadResourceProcess(altPath, loadExact, initData); if (altResource != nullptr) { return altResource; @@ -99,7 +101,7 @@ std::shared_ptr ResourceManager::LoadResourceProcess(const std::strin } // Get the file from the OTR - auto file = LoadFileProcess(filePath); + auto file = LoadFileProcess(filePath, initData); if (file == nullptr) { SPDLOG_TRACE("Failed to load resource file at path {}", filePath); } @@ -136,20 +138,9 @@ std::shared_ptr ResourceManager::LoadResourceProcess(const std::strin return resource; } -std::shared_future> ResourceManager::LoadFileAsync(const std::string& filePath, bool priority) { - if (priority) { - return mThreadPool->submit_front(&ResourceManager::LoadFileProcess, this, filePath).share(); - } else { - return mThreadPool->submit_back(&ResourceManager::LoadFileProcess, this, filePath).share(); - } -} - -std::shared_ptr ResourceManager::LoadFile(const std::string& filePath) { - return LoadFileAsync(filePath, true).get(); -} - -std::shared_future> ResourceManager::LoadResourceAsync(const std::string& filePath, - bool loadExact, bool priority) { +std::shared_future> +ResourceManager::LoadResourceAsync(const std::string& filePath, bool loadExact, bool priority, + std::shared_ptr initData) { // Check for and remove the OTR signature if (OtrSignatureCheck(filePath.c_str())) { auto newFilePath = filePath.substr(7); @@ -167,14 +158,15 @@ std::shared_future> ResourceManager::LoadResourceAsyn const auto newFilePath = std::string(filePath); if (priority) { - return mThreadPool->submit_front(&ResourceManager::LoadResourceProcess, this, newFilePath, loadExact); + return mThreadPool->submit_front(&ResourceManager::LoadResourceProcess, this, newFilePath, loadExact, initData); } else { - return mThreadPool->submit_back(&ResourceManager::LoadResourceProcess, this, newFilePath, loadExact); + return mThreadPool->submit_back(&ResourceManager::LoadResourceProcess, this, newFilePath, loadExact, initData); } } -std::shared_ptr ResourceManager::LoadResource(const std::string& filePath, bool loadExact) { - auto resource = LoadResourceAsync(filePath, loadExact, true).get(); +std::shared_ptr ResourceManager::LoadResource(const std::string& filePath, bool loadExact, + std::shared_ptr initData) { + auto resource = LoadResourceAsync(filePath, loadExact, true, initData).get(); if (resource == nullptr) { SPDLOG_ERROR("Failed to load resource file at path {}", filePath); } diff --git a/src/resource/ResourceManager.h b/src/resource/ResourceManager.h index 7b48dd2a9..3c0cb6500 100644 --- a/src/resource/ResourceManager.h +++ b/src/resource/ResourceManager.h @@ -29,14 +29,15 @@ class ResourceManager { bool DidLoadSuccessfully(); std::shared_ptr GetArchiveManager(); std::shared_ptr GetResourceLoader(); - std::shared_future> LoadFileAsync(const std::string& filePath, bool priority = false); - std::shared_ptr LoadFile(const std::string& filePath); std::shared_ptr GetCachedResource(const std::string& filePath, bool loadExact = false); - std::shared_ptr LoadResource(const std::string& filePath, bool loadExact = false); - std::shared_ptr LoadResourceProcess(const std::string& filePath, bool loadExact = false); + std::shared_ptr LoadResource(const std::string& filePath, bool loadExact = false, + std::shared_ptr initData = nullptr); + std::shared_ptr LoadResourceProcess(const std::string& filePath, bool loadExact = false, + std::shared_ptr initData = nullptr); size_t UnloadResource(const std::string& filePath); - std::shared_future> LoadResourceAsync(const std::string& filePath, - bool loadExact = false, bool priority = false); + std::shared_future> + LoadResourceAsync(const std::string& filePath, bool loadExact = false, bool priority = false, + std::shared_ptr initData = nullptr); std::shared_ptr>> LoadDirectory(const std::string& searchMask); std::shared_ptr>>> LoadDirectoryAsync(const std::string& searchMask, bool priority = false); @@ -45,7 +46,8 @@ class ResourceManager { bool OtrSignatureCheck(const char* fileName); protected: - std::shared_ptr LoadFileProcess(const std::string& filePath); + std::shared_ptr LoadFileProcess(const std::string& filePath, + std::shared_ptr initData = nullptr); std::shared_ptr GetCachedResource(std::variant> cacheLine); std::variant> CheckCache(const std::string& filePath, bool loadExact = false); diff --git a/src/resource/archive/Archive.cpp b/src/resource/archive/Archive.cpp index 926a66005..675851b77 100644 --- a/src/resource/archive/Archive.cpp +++ b/src/resource/archive/Archive.cpp @@ -203,18 +203,24 @@ std::shared_ptr Archive::CreateXMLReader(std::shared_ptr< return xmlReader; } -std::shared_ptr Archive::LoadFile(const std::string& filePath) { - auto metaFilePath = filePath + ".meta"; - auto metaFileToLoad = LoadFileRaw(metaFilePath); - +std::shared_ptr Archive::LoadFile(const std::string& filePath, std::shared_ptr initData) { std::shared_ptr fileToLoad = nullptr; - if (metaFileToLoad != nullptr) { - auto initData = ReadResourceInitData(filePath, metaFileToLoad); - fileToLoad = LoadFileRaw(initData->Path); + + if (initData != nullptr) { + fileToLoad = LoadFileRaw(filePath); fileToLoad->InitData = initData; } else { - fileToLoad = LoadFileRaw(filePath); - fileToLoad->InitData = ReadResourceInitDataLegacy(filePath, fileToLoad); + auto metaFilePath = filePath + ".meta"; + auto metaFileToLoad = LoadFileRaw(metaFilePath); + + if (metaFileToLoad != nullptr) { + auto initDataFromMetaFile = ReadResourceInitData(filePath, metaFileToLoad); + fileToLoad = LoadFileRaw(initDataFromMetaFile->Path); + fileToLoad->InitData = initDataFromMetaFile; + } else { + fileToLoad = LoadFileRaw(filePath); + fileToLoad->InitData = ReadResourceInitDataLegacy(filePath, fileToLoad); + } } if (fileToLoad == nullptr) { @@ -234,10 +240,10 @@ std::shared_ptr Archive::LoadFile(const std::string& filePath) { return fileToLoad; } -std::shared_ptr Archive::LoadFile(uint64_t hash) { +std::shared_ptr Archive::LoadFile(uint64_t hash, std::shared_ptr initData) { const std::string& filePath = *Context::GetInstance()->GetResourceManager()->GetArchiveManager()->HashToString(hash); - return LoadFile(filePath); + return LoadFile(filePath, initData); } std::shared_ptr Archive::CreateDefaultResourceInitData() { diff --git a/src/resource/archive/Archive.h b/src/resource/archive/Archive.h index 8ca75e580..e9ad20bb5 100644 --- a/src/resource/archive/Archive.h +++ b/src/resource/archive/Archive.h @@ -23,8 +23,9 @@ class Archive { void Load(); void Unload(); - virtual std::shared_ptr LoadFile(const std::string& filePath); - virtual std::shared_ptr LoadFile(uint64_t hash); + virtual std::shared_ptr LoadFile(const std::string& filePath, + std::shared_ptr initData = nullptr); + virtual std::shared_ptr LoadFile(uint64_t hash, std::shared_ptr initData = nullptr); std::shared_ptr> ListFiles(); std::shared_ptr> ListFiles(const std::string& filter); bool HasFile(const std::string& filePath); diff --git a/src/resource/archive/ArchiveManager.cpp b/src/resource/archive/ArchiveManager.cpp index f8b4356b4..f6a9f9404 100644 --- a/src/resource/archive/ArchiveManager.cpp +++ b/src/resource/archive/ArchiveManager.cpp @@ -40,21 +40,22 @@ bool ArchiveManager::IsArchiveLoaded() { return !mArchives.empty(); } -std::shared_ptr ArchiveManager::LoadFile(const std::string& filePath) { +std::shared_ptr ArchiveManager::LoadFile(const std::string& filePath, + std::shared_ptr initData) { if (filePath == "") { return nullptr; } - return LoadFile(CRC64(filePath.c_str())); + return LoadFile(CRC64(filePath.c_str()), initData); } -std::shared_ptr ArchiveManager::LoadFile(uint64_t hash) { +std::shared_ptr ArchiveManager::LoadFile(uint64_t hash, std::shared_ptr initData) { const auto archive = mFileToArchive[hash]; if (archive == nullptr) { return nullptr; } - auto file = archive->LoadFile(hash); + auto file = archive->LoadFile(hash, initData); file->Parent = archive; return file; } diff --git a/src/resource/archive/ArchiveManager.h b/src/resource/archive/ArchiveManager.h index 1bcdb4503..0d6fc2e5e 100644 --- a/src/resource/archive/ArchiveManager.h +++ b/src/resource/archive/ArchiveManager.h @@ -6,6 +6,7 @@ #include #include #include +#include "resource/File.h" namespace LUS { struct File; @@ -19,8 +20,8 @@ class ArchiveManager { ~ArchiveManager(); bool IsArchiveLoaded(); - std::shared_ptr LoadFile(const std::string& filePath); - std::shared_ptr LoadFile(uint64_t hash); + std::shared_ptr LoadFile(const std::string& filePath, std::shared_ptr initData = nullptr); + std::shared_ptr LoadFile(uint64_t hash, std::shared_ptr initData = nullptr); std::shared_ptr LoadFileRaw(const std::string& filePath); std::shared_ptr LoadFileRaw(uint64_t hash); bool HasFile(const std::string& filePath); diff --git a/src/window/gui/GameOverlay.cpp b/src/window/gui/GameOverlay.cpp index 5cbe66d03..56f6cee98 100644 --- a/src/window/gui/GameOverlay.cpp +++ b/src/window/gui/GameOverlay.cpp @@ -2,6 +2,8 @@ #include "public/bridge/consolevariablebridge.h" #include "resource/File.h" +#include "window/gui/resource/Font.h" +#include "window/gui/resource/FontFactory.h" #include "resource/archive/Archive.h" #include "resource/ResourceManager.h" #include "Context.h" @@ -17,12 +19,14 @@ GameOverlay::~GameOverlay() { void GameOverlay::LoadFont(const std::string& name, const std::string& path, float fontSize) { ImGuiIO& io = ImGui::GetIO(); - std::shared_ptr font = Context::GetInstance()->GetResourceManager()->GetArchiveManager()->LoadFileRaw(path); - if (font->IsLoaded) { - // TODO: Nothing is ever unloading the font or this fontData array. - char* fontData = new char[font->Buffer->size()]; - memcpy(fontData, font->Buffer->data(), font->Buffer->size()); - mFonts[name] = io.Fonts->AddFontFromMemoryTTF(fontData, font->Buffer->size(), fontSize); + auto initData = std::make_shared(); + initData->Format = RESOURCE_FORMAT_BINARY; + initData->Type = static_cast(RESOURCE_TYPE_FONT); + initData->ResourceVersion = 0; + std::shared_ptr font = std::static_pointer_cast( + Context::GetInstance()->GetResourceManager()->LoadResource(path, false, initData)); + if (font != nullptr) { + mFonts[name] = io.Fonts->AddFontFromMemoryTTF(font->Data, font->DataSize, fontSize); } } @@ -127,6 +131,9 @@ ImVec2 GameOverlay::CalculateTextSize(const char* text, const char* textEnd, boo } void GameOverlay::Init() { + Context::GetInstance()->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory( + std::make_shared(), RESOURCE_FORMAT_BINARY, "Font", + static_cast(RESOURCE_TYPE_FONT), 0); LoadFont("Press Start 2P", "fonts/PressStart2P-Regular.ttf", 12.0f); LoadFont("Fipps", "fonts/Fipps-Regular.otf", 32.0f); const std::string defaultFont = mFonts.begin()->first; diff --git a/src/window/gui/resource/Font.cpp b/src/window/gui/resource/Font.cpp new file mode 100644 index 000000000..e953cd450 --- /dev/null +++ b/src/window/gui/resource/Font.cpp @@ -0,0 +1,20 @@ +#include "Font.h" + +namespace LUS { +Font::Font() : Resource(std::shared_ptr()) { +} + +Font::~Font() { + if (Data != nullptr) { + delete Data; + } +} + +void* Font::GetPointer() { + return Data; +} + +size_t Font::GetPointerSize() { + return DataSize * sizeof(char); +} +} // namespace LUS diff --git a/src/window/gui/resource/Font.h b/src/window/gui/resource/Font.h new file mode 100644 index 000000000..c6ec4cf22 --- /dev/null +++ b/src/window/gui/resource/Font.h @@ -0,0 +1,21 @@ +#pragma once + +#include "resource/Resource.h" + +namespace LUS { +#define RESOURCE_TYPE_FONT 0x464F4E54 // FONT + +class Font : public Resource { + public: + using Resource::Resource; + + Font(); + ~Font(); + + void* GetPointer() override; + size_t GetPointerSize() override; + + char* Data = nullptr; + size_t DataSize; +}; +}; // namespace LUS diff --git a/src/window/gui/resource/FontFactory.cpp b/src/window/gui/resource/FontFactory.cpp new file mode 100644 index 000000000..2dd31d6bd --- /dev/null +++ b/src/window/gui/resource/FontFactory.cpp @@ -0,0 +1,25 @@ +#include "window/gui/resource/FontFactory.h" +#include "window/gui/resource/Font.h" +#include "spdlog/spdlog.h" + +namespace LUS { +std::shared_ptr ResourceFactoryBinaryFontV0::ReadResource(std::shared_ptr file) { + if (!FileHasValidFormatAndReader(file)) { + return nullptr; + } + + auto font = std::make_shared(file->InitData); + auto reader = std::get>(file->Reader); + + font->DataSize = file->Buffer->size(); + + font->Data = new char[font->DataSize]; + reader->Read(font->Data, font->DataSize); + + // for (uint32_t i = 0; i < dataSize; i++) { + // font->Data.push_back(reader->ReadChar()); + // } + + return font; +} +} // namespace LUS diff --git a/src/window/gui/resource/FontFactory.h b/src/window/gui/resource/FontFactory.h new file mode 100644 index 000000000..202dc2d98 --- /dev/null +++ b/src/window/gui/resource/FontFactory.h @@ -0,0 +1,11 @@ +#pragma once + +#include "resource/Resource.h" +#include "resource/ResourceFactoryBinary.h" + +namespace LUS { +class ResourceFactoryBinaryFontV0 : public ResourceFactoryBinary { + public: + std::shared_ptr ReadResource(std::shared_ptr file) override; +}; +}; // namespace LUS