-
Notifications
You must be signed in to change notification settings - Fork 28
Added Font_s dumper and loader #739
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,134 @@ | ||
| #include "AssetLoaderFontIW3.h" | ||
| #include "Game/IW3/IW3.h" | ||
| #include "Utils/Logging/Log.h" | ||
|
|
||
| #include <nlohmann/json.hpp> | ||
| #include <cstring> | ||
| #include <format> | ||
|
|
||
| using namespace IW3; | ||
|
|
||
| namespace | ||
| { | ||
| class FontLoader final : public AssetCreator<AssetFont> | ||
| { | ||
| public: | ||
| FontLoader(MemoryManager& memory, ISearchPath& searchPath) | ||
| : m_memory(memory), | ||
| m_search_path(searchPath) | ||
| { | ||
| } | ||
|
|
||
| AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override | ||
| { | ||
| const auto file = m_search_path.Open(std::format("{}.json", assetName)); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What other assets do is having a "common" file in the "ObjCommon" component that returns the file name for an asset, e.g. MaterialCommon.h. This makes it possible to have a single source of truth for the filename pattern that is shared between dumpers and loaders. |
||
| if (!file.IsOpen()) | ||
| return AssetCreationResult::NoAction(); | ||
|
|
||
| auto* font = m_memory.Alloc<Font_s>(); | ||
| std::memset(font, 0, sizeof(Font_s)); | ||
|
|
||
| AssetRegistration<AssetFont> registration(assetName, font); | ||
|
|
||
| if (!LoadFromJson(*file.m_stream, *font, context, registration)) | ||
| { | ||
| con::error("Failed to load font \"{}\"", assetName); | ||
| return AssetCreationResult::Failure(); | ||
| } | ||
|
|
||
| return AssetCreationResult::Success(context.AddAsset(std::move(registration))); | ||
| } | ||
|
|
||
| private: | ||
| bool LoadFromJson(std::istream& jsonStream, Font_s& font, AssetCreationContext& context, AssetRegistration<AssetFont>& registration) | ||
| { | ||
| try | ||
| { | ||
| const auto jRoot = nlohmann::json::parse(jsonStream); | ||
|
|
||
| std::string type; | ||
| jRoot.at("_type").get_to(type); | ||
|
|
||
| if (type != "font") | ||
| { | ||
| con::error("Tried to load font but did not find expected type 'font'"); | ||
| return false; | ||
| } | ||
|
|
||
| font.pixelHeight = jRoot.value("pixelHeight", 0); | ||
| font.glyphCount = jRoot.value("glyphCount", 0); | ||
|
Comment on lines
+58
to
+59
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This project uses the arbitrary type conversions feature of nlohmann json, e.g. see JsonLeaderboardDef.h for the types and JsonLoaderFontIconT6.cpp on them getting used. Makes the loading code less verbose, prone to errors and makes the target format clearer in code imo. Would be nice to not have this be an outlier in what style it uses😅
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like your usage of ordered_json and i noticed that the extensions for arbitrary type conversions for nlohmann json i defined only support the normal json and not ordered_json. I got to fix that i guess 😅
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did this here: #746 if you wanna use ordered_json still with arbitrary type conversions, feel free to rebase on main when its merged |
||
|
|
||
| std::string fontName = jRoot.value("name", ""); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The name part of the font asset should be taken from the input arguments of the loader (and the "name" should not be part of the json). Otherwise you could try to load a font asset with one name and get an entirely different name (potentially by accident because you renamed the file but not the value in it) |
||
| font.fontName = m_memory.Dup(fontName.c_str()); | ||
|
|
||
| if (jRoot.contains("material") && !jRoot["material"].is_null()) | ||
| { | ||
| std::string matName = jRoot["material"]; | ||
| auto* matInfo = context.LoadDependency<AssetMaterial>(matName); | ||
| if (!matInfo) | ||
| { | ||
| con::error("Font \"{}\" missing dependency material \"{}\"", font.fontName, matName); | ||
| return false; | ||
| } | ||
| registration.AddDependency(matInfo); | ||
| font.material = matInfo->Asset(); | ||
| } | ||
|
|
||
| if (jRoot.contains("glowMaterial") && !jRoot["glowMaterial"].is_null()) | ||
| { | ||
| std::string glowMatName = jRoot["glowMaterial"]; | ||
| auto* glowMatInfo = context.LoadDependency<AssetMaterial>(glowMatName); | ||
| if (glowMatInfo) | ||
| { | ||
| registration.AddDependency(glowMatInfo); | ||
| font.glowMaterial = glowMatInfo->Asset(); | ||
| } | ||
| } | ||
|
|
||
| if (font.glyphCount > 0 && jRoot.contains("glyphs")) | ||
| { | ||
| const auto& jGlyphs = jRoot["glyphs"]; | ||
| font.glyphs = m_memory.Alloc<Glyph>(font.glyphCount); | ||
|
|
||
| for (int i = 0; i < font.glyphCount; ++i) | ||
| { | ||
| const auto& jG = jGlyphs[i]; | ||
| auto& g = font.glyphs[i]; | ||
|
|
||
| g.letter = jG.value("letter", 0); | ||
|
|
||
| g.x0 = static_cast<char>(jG.value("x0", 0)); | ||
| g.y0 = static_cast<char>(jG.value("y0", 0)); | ||
| g.dx = static_cast<char>(jG.value("dx", 0)); | ||
| g.pixelWidth = static_cast<char>(jG.value("width", 0)); | ||
| g.pixelHeight = static_cast<char>(jG.value("height", 0)); | ||
|
Comment on lines
+102
to
+104
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I made a mistake on the game types here, |
||
|
|
||
| g.s0 = jG.value("s0", 0.0f); | ||
| g.t0 = jG.value("t0", 0.0f); | ||
| g.s1 = jG.value("s1", 0.0f); | ||
| g.t1 = jG.value("t1", 0.0f); | ||
| } | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
| catch (const nlohmann::json::exception& e) | ||
| { | ||
| con::error("Failed to parse json of font: {}", e.what()); | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| MemoryManager& m_memory; | ||
| ISearchPath& m_search_path; | ||
| }; | ||
| } // namespace | ||
|
|
||
| namespace font | ||
| { | ||
| std::unique_ptr<AssetCreator<AssetFont>> CreateLoaderIW3(MemoryManager& memory, ISearchPath& searchPath) | ||
| { | ||
| return std::make_unique<FontLoader>(memory, searchPath); | ||
| } | ||
| } // namespace font | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| #pragma once | ||
|
|
||
| #include "Asset/IAssetCreator.h" | ||
| #include "Game/IW3/IW3.h" | ||
| #include "SearchPath/ISearchPath.h" | ||
| #include "Utils/MemoryManager.h" | ||
|
|
||
| #include <memory> | ||
|
|
||
| namespace font | ||
| { | ||
| std::unique_ptr<AssetCreator<IW3::AssetFont>> CreateLoaderIW3(MemoryManager& memory, ISearchPath& searchPath); | ||
| } // namespace font |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,134 @@ | ||
| #include "AssetLoaderFontIW4.h" | ||
| #include "Game/IW4/IW4.h" | ||
| #include "Utils/Logging/Log.h" | ||
|
|
||
| #include <nlohmann/json.hpp> | ||
| #include <cstring> | ||
| #include <format> | ||
|
|
||
| using namespace IW4; | ||
|
|
||
| namespace | ||
| { | ||
| class FontLoader final : public AssetCreator<AssetFont> | ||
| { | ||
| public: | ||
| FontLoader(MemoryManager& memory, ISearchPath& searchPath) | ||
| : m_memory(memory), | ||
| m_search_path(searchPath) | ||
| { | ||
| } | ||
|
|
||
| AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override | ||
| { | ||
| const auto file = m_search_path.Open(std::format("{}.json", assetName)); | ||
| if (!file.IsOpen()) | ||
| return AssetCreationResult::NoAction(); | ||
|
|
||
| auto* font = m_memory.Alloc<Font_s>(); | ||
| std::memset(font, 0, sizeof(Font_s)); | ||
|
|
||
| AssetRegistration<AssetFont> registration(assetName, font); | ||
|
|
||
| if (!LoadFromJson(*file.m_stream, *font, context, registration)) | ||
| { | ||
| con::error("Failed to load font \"{}\"", assetName); | ||
| return AssetCreationResult::Failure(); | ||
| } | ||
|
|
||
| return AssetCreationResult::Success(context.AddAsset(std::move(registration))); | ||
| } | ||
|
|
||
| private: | ||
| bool LoadFromJson(std::istream& jsonStream, Font_s& font, AssetCreationContext& context, AssetRegistration<AssetFont>& registration) | ||
| { | ||
| try | ||
| { | ||
| const auto jRoot = nlohmann::json::parse(jsonStream); | ||
|
|
||
| std::string type; | ||
| jRoot.at("_type").get_to(type); | ||
|
|
||
| if (type != "font") | ||
| { | ||
| con::error("Tried to load font but did not find expected type 'font'"); | ||
| return false; | ||
| } | ||
|
|
||
| font.pixelHeight = jRoot.value("pixelHeight", 0); | ||
| font.glyphCount = jRoot.value("glyphCount", 0); | ||
|
|
||
| std::string fontName = jRoot.value("name", ""); | ||
| font.fontName = m_memory.Dup(fontName.c_str()); | ||
|
|
||
| if (jRoot.contains("material") && !jRoot["material"].is_null()) | ||
| { | ||
| std::string matName = jRoot["material"]; | ||
| auto* matInfo = context.LoadDependency<AssetMaterial>(matName); | ||
| if (!matInfo) | ||
| { | ||
| con::error("Font \"{}\" missing dependency material \"{}\"", font.fontName, matName); | ||
| return false; | ||
| } | ||
| registration.AddDependency(matInfo); | ||
| font.material = matInfo->Asset(); | ||
| } | ||
|
|
||
| if (jRoot.contains("glowMaterial") && !jRoot["glowMaterial"].is_null()) | ||
| { | ||
| std::string glowMatName = jRoot["glowMaterial"]; | ||
| auto* glowMatInfo = context.LoadDependency<AssetMaterial>(glowMatName); | ||
| if (glowMatInfo) | ||
| { | ||
| registration.AddDependency(glowMatInfo); | ||
| font.glowMaterial = glowMatInfo->Asset(); | ||
| } | ||
| } | ||
|
|
||
| if (font.glyphCount > 0 && jRoot.contains("glyphs")) | ||
| { | ||
| const auto& jGlyphs = jRoot["glyphs"]; | ||
| font.glyphs = m_memory.Alloc<Glyph>(font.glyphCount); | ||
|
|
||
| for (int i = 0; i < font.glyphCount; ++i) | ||
| { | ||
| const auto& jG = jGlyphs[i]; | ||
| auto& g = font.glyphs[i]; | ||
|
|
||
| g.letter = jG.value("letter", 0); | ||
|
|
||
| g.x0 = static_cast<char>(jG.value("x0", 0)); | ||
| g.y0 = static_cast<char>(jG.value("y0", 0)); | ||
| g.dx = static_cast<char>(jG.value("dx", 0)); | ||
| g.pixelWidth = static_cast<char>(jG.value("width", 0)); | ||
| g.pixelHeight = static_cast<char>(jG.value("height", 0)); | ||
|
|
||
| g.s0 = jG.value("s0", 0.0f); | ||
| g.t0 = jG.value("t0", 0.0f); | ||
| g.s1 = jG.value("s1", 0.0f); | ||
| g.t1 = jG.value("t1", 0.0f); | ||
| } | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
| catch (const nlohmann::json::exception& e) | ||
| { | ||
| con::error("Failed to parse json of font: {}", e.what()); | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| MemoryManager& m_memory; | ||
| ISearchPath& m_search_path; | ||
| }; | ||
| } // namespace | ||
|
|
||
| namespace font | ||
| { | ||
| std::unique_ptr<AssetCreator<AssetFont>> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath) | ||
| { | ||
| return std::make_unique<FontLoader>(memory, searchPath); | ||
| } | ||
| } // namespace font |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| #pragma once | ||
|
|
||
| #include "Asset/IAssetCreator.h" | ||
| #include "Game/IW4/IW4.h" | ||
| #include "SearchPath/ISearchPath.h" | ||
| #include "Utils/MemoryManager.h" | ||
|
|
||
| #include <memory> | ||
|
|
||
| namespace font | ||
| { | ||
| std::unique_ptr<AssetCreator<IW4::AssetFont>> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath); | ||
| } // namespace font |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The project uses clang-format for formatting. You should be able to configure clang-format as formatter in most IDEs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay i'm try add it formatter in visual studio, vs always used own standard 🤣