mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2026-07-19 14:30:37 +00:00
feat: T6 font_s dumper (#850)
* feat: T6 font dumper * feat: implement templated loader and writer for fonts in t6 --------- Co-authored-by: Jan Laupetin <[email protected]>
This commit is contained in:
@@ -214,7 +214,7 @@ using `Linker`):
|
||||
| MapEnts | ✅ | ❌ | |
|
||||
| GfxWorld | ❌ | ❌ | |
|
||||
| GfxLightDef | ✅ | ✅ | |
|
||||
| Font_s | ❌ | ❌ | |
|
||||
| Font_s | ✅ | ✅ | |
|
||||
| FontIcon | ✅ | ✅ | |
|
||||
| MenuList | ❌ | ❌ | |
|
||||
| menuDef_t | ❌ | ❌ | |
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
#options GAME (IW3, IW4, IW5, T4, T5)
|
||||
#options GAME (IW3, IW4, IW5, T4, T5, T6)
|
||||
|
||||
#filename "Game/" + GAME + "/Font/JsonFont" + GAME + ".h"
|
||||
|
||||
#if GAME == "T6"
|
||||
#define FEATURE_T6
|
||||
#endif
|
||||
|
||||
// This file was templated.
|
||||
// See JsonFont.h.template.
|
||||
// Do not modify, changes will be lost.
|
||||
@@ -54,14 +58,76 @@ namespace GAME
|
||||
NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(EXTEND_JSON_FROM, x0, y0, dx, pixelWidth, pixelHeight, s0, t0, s1, t1))
|
||||
}
|
||||
|
||||
#ifdef FEATURE_T6
|
||||
class JsonKerningPair
|
||||
{
|
||||
public:
|
||||
unsigned firstLetter;
|
||||
unsigned secondLetter;
|
||||
int kernAmount;
|
||||
};
|
||||
|
||||
NLOHMANN_TO_JSON_METHOD(JsonKerningPair)
|
||||
{
|
||||
if (font::IsPrintableLetter(nlohmann_json_t.firstLetter))
|
||||
extended_to_json("firstLetter", nlohmann_json_j, font::LetterToString(nlohmann_json_t.firstLetter));
|
||||
else
|
||||
extended_to_json("firstLetter", nlohmann_json_j, nlohmann_json_t.firstLetter);
|
||||
|
||||
if (font::IsPrintableLetter(nlohmann_json_t.secondLetter))
|
||||
extended_to_json("secondLetter", nlohmann_json_j, font::LetterToString(nlohmann_json_t.secondLetter));
|
||||
else
|
||||
extended_to_json("secondLetter", nlohmann_json_j, nlohmann_json_t.secondLetter);
|
||||
|
||||
NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(EXTEND_JSON_TO, kernAmount))
|
||||
}
|
||||
|
||||
NLOHMANN_FROM_JSON_METHOD(JsonKerningPair)
|
||||
{
|
||||
auto jLetter = nlohmann_json_j.at("firstLetter");
|
||||
if (jLetter.type() == BasicJsonType::value_t::string)
|
||||
nlohmann_json_t.firstLetter = font::StringToLetter(jLetter.template get<std::string>());
|
||||
else
|
||||
nlohmann_json_t.firstLetter = jLetter.template get<unsigned>();
|
||||
|
||||
jLetter = nlohmann_json_j.at("secondLetter");
|
||||
if (jLetter.type() == BasicJsonType::value_t::string)
|
||||
nlohmann_json_t.secondLetter = font::StringToLetter(jLetter.template get<std::string>());
|
||||
else
|
||||
nlohmann_json_t.secondLetter = jLetter.template get<unsigned>();
|
||||
|
||||
NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(EXTEND_JSON_FROM, kernAmount))
|
||||
}
|
||||
#endif
|
||||
|
||||
class JsonFont
|
||||
{
|
||||
public:
|
||||
unsigned pixelHeight;
|
||||
#ifdef FEATURE_T6
|
||||
bool isScalingAllowed;
|
||||
#endif
|
||||
std::string material;
|
||||
std::optional<std::string> glowMaterial;
|
||||
std::vector<JsonGlyph> glyphs;
|
||||
#ifdef FEATURE_T6
|
||||
std::vector<JsonKerningPair> kerningPairs;
|
||||
#endif
|
||||
};
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_EXTENSION(JsonFont, pixelHeight, material, glowMaterial, glyphs);
|
||||
NLOHMANN_DEFINE_TYPE_EXTENSION(
|
||||
JsonFont,
|
||||
pixelHeight,
|
||||
#ifdef FEATURE_T6
|
||||
isScalingAllowed,
|
||||
#endif
|
||||
material,
|
||||
glowMaterial,
|
||||
#ifdef FEATURE_T6
|
||||
glyphs,
|
||||
kerningPairs
|
||||
#else
|
||||
glyphs
|
||||
#endif
|
||||
);
|
||||
} // namespace GAME
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#options GAME (IW3, IW4, IW5, T4, T5)
|
||||
#options GAME (IW3, IW4, IW5, T4, T5, T6)
|
||||
|
||||
#filename "Game/" + GAME + "/Font/FontLoader" + GAME + ".cpp"
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
#define GAME_LOWER "t4"
|
||||
#elif GAME == "T5"
|
||||
#define GAME_LOWER "t5"
|
||||
#elif GAME == "T6"
|
||||
#define GAME_LOWER "t6"
|
||||
#define FEATURE_T6
|
||||
#endif
|
||||
|
||||
// This file was templated.
|
||||
@@ -142,6 +145,56 @@ namespace
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef FEATURE_T6
|
||||
bool CreateKerningPairFromJson(const JsonKerningPair& jKerningPair, KerningPairs& kerningPair, const Font_s& font)
|
||||
{
|
||||
if (!AssignIntegerField(kerningPair.wFirst, jKerningPair.firstLetter, font, "kerningPair.firstLetter"))
|
||||
return false;
|
||||
if (!AssignIntegerField(kerningPair.wSecond, jKerningPair.secondLetter, font, "kerningPair.secondLetter"))
|
||||
return false;
|
||||
if (!AssignIntegerField(kerningPair.iKernAmount, jKerningPair.kernAmount, font, "kerningPair.kernAmount"))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SortKerningPairs(const Font_s& font)
|
||||
{
|
||||
std::sort(&font.kerningPairs[0], &font.kerningPairs[font.kerningPairsCount], [](const KerningPairs& a, const KerningPairs& b)
|
||||
{
|
||||
if (a.wFirst != b.wFirst)
|
||||
return a.wFirst < b.wFirst;
|
||||
|
||||
return a.wSecond < b.wSecond;
|
||||
});
|
||||
}
|
||||
|
||||
bool EnsureFontContainsKerningPairLetter(const Font_s& font, const unsigned letter)
|
||||
{
|
||||
for (auto i = 0; i < font.glyphCount; i++)
|
||||
{
|
||||
const auto& glyph = font.glyphs[i];
|
||||
if (glyph.letter == letter)
|
||||
return true;
|
||||
}
|
||||
|
||||
con::error("Font {} has kerning pair with letter {} ('{}') but no glyph for it", font.fontName, letter, static_cast<char>(letter));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EnsureFontContainsGlyphsOfKerningPairs(const Font_s& font)
|
||||
{
|
||||
for (auto i = 0; i < font.kerningPairsCount; i++)
|
||||
{
|
||||
const auto& kerningPair = font.kerningPairs[i];
|
||||
if (!EnsureFontContainsKerningPairLetter(font, kerningPair.wFirst) || !EnsureFontContainsKerningPairLetter(font, kerningPair.wSecond))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
class FontLoader final : public AssetCreator<AssetFont>
|
||||
{
|
||||
public:
|
||||
@@ -200,6 +253,10 @@ namespace
|
||||
bool CreateFontFromJson(const JsonFont& jFont, Font_s& font, AssetRegistration<AssetFont>& registration, AssetCreationContext& context) const
|
||||
{
|
||||
font.pixelHeight = static_cast<decltype(Font_s::pixelHeight)>(jFont.pixelHeight);
|
||||
|
||||
#ifdef FEATURE_T6
|
||||
font.isScalingAllowed = jFont.isScalingAllowed;
|
||||
#endif
|
||||
|
||||
if (!CreateMaterialDependency(jFont.material, font.material, registration, context, font, "font"))
|
||||
return false;
|
||||
@@ -217,25 +274,48 @@ namespace
|
||||
return false;
|
||||
}
|
||||
|
||||
font.glyphCount = static_cast<decltype(Font_s::glyphCount)>(jFont.glyphs.size());;
|
||||
if (font.glyphCount <= 0)
|
||||
font.glyphCount = static_cast<decltype(Font_s::glyphCount)>(jFont.glyphs.size());
|
||||
if (font.glyphCount > 0)
|
||||
{
|
||||
font.glyphs = m_memory.Alloc<Glyph>(font.glyphCount);
|
||||
for (auto i = 0; i < font.glyphCount; i++)
|
||||
{
|
||||
if (!CreateGlyphFromJson(jFont.glyphs[i], font.glyphs[i], font))
|
||||
return false;
|
||||
}
|
||||
|
||||
SortGlyphs(font);
|
||||
}
|
||||
else
|
||||
{
|
||||
font.glyphs = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
font.glyphs = m_memory.Alloc<Glyph>(font.glyphCount);
|
||||
for (auto i = 0; i < font.glyphCount; i++)
|
||||
{
|
||||
if (!CreateGlyphFromJson(jFont.glyphs[i], font.glyphs[i], font))
|
||||
return false;
|
||||
}
|
||||
|
||||
SortGlyphs(font);
|
||||
|
||||
if (!EnsureFontContainsAllRequiredGlyphs(font))
|
||||
return false;
|
||||
|
||||
#ifdef FEATURE_T6
|
||||
font.kerningPairsCount = static_cast<decltype(Font_s::kerningPairsCount)>(jFont.kerningPairs.size());
|
||||
if (font.kerningPairsCount > 0)
|
||||
{
|
||||
font.kerningPairs = m_memory.Alloc<KerningPairs>(font.kerningPairsCount);
|
||||
for (auto i = 0; i < font.kerningPairsCount; i++)
|
||||
{
|
||||
if (!CreateKerningPairFromJson(jFont.kerningPairs[i], font.kerningPairs[i], font))
|
||||
return false;
|
||||
}
|
||||
|
||||
SortKerningPairs(font);
|
||||
}
|
||||
else
|
||||
{
|
||||
font.kerningPairs = nullptr;
|
||||
}
|
||||
|
||||
if (!EnsureFontContainsGlyphsOfKerningPairs(font))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#options GAME (IW3, IW4, IW5, T4, T5)
|
||||
#options GAME (IW3, IW4, IW5, T4, T5, T6)
|
||||
|
||||
#filename "Game/" + GAME + "/Font/FontLoader" + GAME + ".h"
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "FontIcon/JsonLoaderFontIconT6.h"
|
||||
#include "Game/T6/AssetMarkerT6.h"
|
||||
#include "Game/T6/CommonT6.h"
|
||||
#include "Game/T6/Font/FontLoaderT6.h"
|
||||
#include "Game/T6/GameT6.h"
|
||||
#include "Game/T6/Image/ImageLoaderEmbeddedT6.h"
|
||||
#include "Game/T6/Image/ImageLoaderExternalT6.h"
|
||||
@@ -404,7 +405,7 @@ namespace T6
|
||||
// collection.AddAssetCreator(std::make_unique<AssetLoaderMapEnts>(memory));
|
||||
// collection.AddAssetCreator(std::make_unique<AssetLoaderGfxWorld>(memory));
|
||||
collection.AddAssetCreator(light_def::CreateLoaderT6(memory, searchPath));
|
||||
// collection.AddAssetCreator(std::make_unique<AssetLoaderFont>(memory));
|
||||
collection.AddAssetCreator(font::CreateLoaderT6(memory, searchPath));
|
||||
collection.AddAssetCreator(font_icon::CreateCsvLoaderT6(memory, searchPath));
|
||||
collection.AddAssetCreator(font_icon::CreateJsonLoaderT6(memory, searchPath));
|
||||
// collection.AddAssetCreator(std::make_unique<AssetLoaderMenuList>(memory));
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#options GAME (IW3, IW4, IW5, T4, T5)
|
||||
#options GAME (IW3, IW4, IW5, T4, T5, T6)
|
||||
|
||||
#filename "Game/" + GAME + "/Font/FontDumper" + GAME + ".cpp"
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
#define GAME_LOWER "t4"
|
||||
#elif GAME == "T5"
|
||||
#define GAME_LOWER "t5"
|
||||
#elif GAME == "T6"
|
||||
#define FEATURE_T6
|
||||
#define GAME_LOWER "t6"
|
||||
#endif
|
||||
|
||||
// This file was templated.
|
||||
@@ -57,9 +60,22 @@ namespace
|
||||
jGlyph.t1 = glyph.t1;
|
||||
}
|
||||
|
||||
#ifdef FEATURE_T6
|
||||
void CreateJsonKerningPair(JsonKerningPair& jKerningPair, const KerningPairs& kerningPair)
|
||||
{
|
||||
jKerningPair.firstLetter = kerningPair.wFirst;
|
||||
jKerningPair.secondLetter = kerningPair.wSecond;
|
||||
jKerningPair.kernAmount = kerningPair.iKernAmount;
|
||||
}
|
||||
#endif
|
||||
|
||||
void CreateJsonFont(JsonFont& jFont, const Font_s& font)
|
||||
{
|
||||
jFont.pixelHeight = font.pixelHeight;
|
||||
|
||||
#ifdef FEATURE_T6
|
||||
jFont.isScalingAllowed = font.isScalingAllowed;
|
||||
#endif
|
||||
|
||||
if (font.material && font.material->info.name)
|
||||
jFont.material = AssetName(font.material->info.name);
|
||||
@@ -73,6 +89,12 @@ namespace
|
||||
jFont.glyphs.resize(font.glyphCount);
|
||||
for (auto i = 0; i < font.glyphCount; i++)
|
||||
CreateJsonGlyph(jFont.glyphs[i], font.glyphs[i]);
|
||||
|
||||
#ifdef FEATURE_T6
|
||||
jFont.kerningPairs.resize(font.kerningPairsCount);
|
||||
for (auto i = 0; i < font.kerningPairsCount; i++)
|
||||
CreateJsonKerningPair(jFont.kerningPairs[i], font.kerningPairs[i]);
|
||||
#endif
|
||||
}
|
||||
|
||||
class Dumper
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#options GAME (IW3, IW4, IW5, T4, T5)
|
||||
#options GAME (IW3, IW4, IW5, T4, T5, T6)
|
||||
|
||||
#filename "Game/" + GAME + "/Font/FontDumper" + GAME + ".h"
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "ObjWriterT6.h"
|
||||
|
||||
#include "FontIcon/FontIconDumperT6.h"
|
||||
#include "Game/T6/Font/FontDumperT6.h"
|
||||
#include "Game/T6/Image/ImageDumperT6.h"
|
||||
#include "Game/T6/Material/MaterialJsonDumperT6.h"
|
||||
#include "Game/T6/Techset/TechsetDumperT6.h"
|
||||
@@ -55,7 +56,7 @@ void ObjWriter::RegisterAssetDumpers(AssetDumpingContext& context)
|
||||
RegisterAssetDumper(std::make_unique<map_ents::DumperT6>());
|
||||
// REGISTER_DUMPER(AssetDumperGfxWorld, m_gfx_world)
|
||||
RegisterAssetDumper(std::make_unique<light_def::DumperT6>());
|
||||
// REGISTER_DUMPER(AssetDumperFont, m_font)
|
||||
RegisterAssetDumper(std::make_unique<font::JsonDumperT6>());
|
||||
RegisterAssetDumper(font_icon::CreateDumperT6());
|
||||
// REGISTER_DUMPER(AssetDumperMenuList, m_menu_list)
|
||||
// REGISTER_DUMPER(AssetDumperMenuDef, m_menu_def)
|
||||
|
||||
Reference in New Issue
Block a user