Load fonticons from csv and alphabetically sort them
This commit is contained in:
parent
2fe9f938af
commit
f17cde2791
@ -41,6 +41,8 @@ namespace Components
|
|||||||
|
|
||||||
unsigned(*TextRenderer::currentColorTable)[TEXT_COLOR_COUNT];
|
unsigned(*TextRenderer::currentColorTable)[TEXT_COLOR_COUNT];
|
||||||
TextRenderer::FontIconAutocompleteContext TextRenderer::autocompleteContextArray[FONT_ICON_ACI_COUNT]{};
|
TextRenderer::FontIconAutocompleteContext TextRenderer::autocompleteContextArray[FONT_ICON_ACI_COUNT]{};
|
||||||
|
std::map<std::string, TextRenderer::FontIconTableEntry> TextRenderer::fontIconLookup;
|
||||||
|
std::vector<TextRenderer::FontIconTableEntry> TextRenderer::fontIconList;
|
||||||
|
|
||||||
Dvar::Var TextRenderer::cg_newColors;
|
Dvar::Var TextRenderer::cg_newColors;
|
||||||
Dvar::Var TextRenderer::cg_fontIconAutocomplete;
|
Dvar::Var TextRenderer::cg_fontIconAutocomplete;
|
||||||
@ -147,16 +149,14 @@ namespace Components
|
|||||||
context.hasMoreResults = false;
|
context.hasMoreResults = false;
|
||||||
context.lastResultOffset = context.resultOffset;
|
context.lastResultOffset = context.resultOffset;
|
||||||
|
|
||||||
const auto* techset2d = Game::DB_FindXAssetHeader(Game::ASSET_TYPE_TECHNIQUE_SET, "2d").techniqueSet;
|
|
||||||
auto skipCount = context.resultOffset;
|
auto skipCount = context.resultOffset;
|
||||||
|
|
||||||
Game::DB_EnumXAssetEntries(Game::ASSET_TYPE_MATERIAL, [&context, techset2d, &skipCount](const Game::XAssetEntry* entry)
|
const auto queryLen = context.lastQuery.size();
|
||||||
|
for(const auto& fontIconEntry : fontIconList)
|
||||||
{
|
{
|
||||||
if (context.resultCount >= FontIconAutocompleteContext::MAX_RESULTS && context.hasMoreResults)
|
const auto compareValue = fontIconEntry.iconName.compare(0, queryLen, context.lastQuery);
|
||||||
return;
|
|
||||||
|
|
||||||
const auto* material = entry->asset.header.material;
|
if (compareValue == 0)
|
||||||
if(material->techniqueSet == techset2d && std::string(material->info.name).rfind(context.lastQuery, 0) == 0)
|
|
||||||
{
|
{
|
||||||
if (skipCount > 0)
|
if (skipCount > 0)
|
||||||
{
|
{
|
||||||
@ -165,14 +165,16 @@ namespace Components
|
|||||||
else if (context.resultCount < FontIconAutocompleteContext::MAX_RESULTS)
|
else if (context.resultCount < FontIconAutocompleteContext::MAX_RESULTS)
|
||||||
{
|
{
|
||||||
context.results[context.resultCount++] = {
|
context.results[context.resultCount++] = {
|
||||||
std::string(Utils::String::VA(":%s:", material->info.name)),
|
Utils::String::VA(":%s:", fontIconEntry.iconName.data()),
|
||||||
std::string(material->info.name)
|
fontIconEntry.iconName
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
context.hasMoreResults = true;
|
context.hasMoreResults = true;
|
||||||
}
|
}
|
||||||
}, false, false);
|
else if (compareValue > 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
context.maxFontIconWidth = 0;
|
context.maxFontIconWidth = 0;
|
||||||
context.maxMaterialNameWidth = 0;
|
context.maxMaterialNameWidth = 0;
|
||||||
@ -606,15 +608,31 @@ namespace Components
|
|||||||
|
|
||||||
const std::string fontIconName(text, nameEnd - text);
|
const std::string fontIconName(text, nameEnd - text);
|
||||||
|
|
||||||
auto* materialEntry = Game::DB_FindXAssetEntry(Game::XAssetType::ASSET_TYPE_MATERIAL, fontIconName.data());
|
const auto foundFontIcon = fontIconLookup.find(fontIconName);
|
||||||
if (materialEntry == nullptr)
|
if (foundFontIcon == fontIconLookup.end())
|
||||||
return false;
|
|
||||||
auto* material = materialEntry->asset.header.material;
|
|
||||||
if (material == nullptr || material->techniqueSet == nullptr || material->techniqueSet->name == nullptr || strcmp(material->techniqueSet->name, "2d") != 0)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
auto& entry = foundFontIcon->second;
|
||||||
|
if(entry.material == nullptr)
|
||||||
|
{
|
||||||
|
auto* materialEntry = Game::DB_FindXAssetEntry(Game::XAssetType::ASSET_TYPE_MATERIAL, entry.materialName.data());
|
||||||
|
if (materialEntry == nullptr)
|
||||||
|
return false;
|
||||||
|
auto* material = materialEntry->asset.header.material;
|
||||||
|
if (material == nullptr || material->techniqueSet == nullptr || material->techniqueSet->name == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(strcmp(material->techniqueSet->name, "2d") != 0)
|
||||||
|
{
|
||||||
|
Logger::Print("^1Fonticon material '%s' does not have 2d techset!\n", material->info.name);
|
||||||
|
material = Game::DB_FindXAssetHeader(Game::ASSET_TYPE_MATERIAL, "default").material;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.material = material;
|
||||||
|
}
|
||||||
|
|
||||||
text = curPos + 1;
|
text = curPos + 1;
|
||||||
fontIcon.material = material;
|
fontIcon.material = entry.material;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1357,6 +1375,58 @@ namespace Components
|
|||||||
(*currentColorTable)[TEXT_COLOR_SERVER] = sv_customTextColor->current.unsignedInt;
|
(*currentColorTable)[TEXT_COLOR_SERVER] = sv_customTextColor->current.unsignedInt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextRenderer::InitFontIcons()
|
||||||
|
{
|
||||||
|
fontIconList.clear();
|
||||||
|
fontIconLookup.clear();
|
||||||
|
|
||||||
|
const auto fontIconTable = Game::DB_FindXAssetHeader(Game::ASSET_TYPE_STRINGTABLE, "mp/fonticons.csv").stringTable;
|
||||||
|
|
||||||
|
if(fontIconTable->columnCount < 2 || fontIconTable->rowCount <= 0)
|
||||||
|
{
|
||||||
|
Logger::Print("^1Failed to load font icon table\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fontIconList.reserve(fontIconTable->rowCount);
|
||||||
|
for(auto rowIndex = 0; rowIndex < fontIconTable->rowCount; rowIndex++)
|
||||||
|
{
|
||||||
|
const auto* columns = &fontIconTable->values[rowIndex * fontIconTable->columnCount];
|
||||||
|
|
||||||
|
if(columns[0].string == nullptr || columns[1].string == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (columns[0].string[0] == '\0' || columns[1].string[1] == '\0')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (columns[0].string[0] == '#')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
FontIconTableEntry entry
|
||||||
|
{
|
||||||
|
columns[0].string,
|
||||||
|
columns[1].string,
|
||||||
|
nullptr
|
||||||
|
};
|
||||||
|
|
||||||
|
fontIconList.emplace_back(entry);
|
||||||
|
fontIconLookup.emplace(std::make_pair(entry.iconName, entry));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(fontIconList.begin(), fontIconList.end(), [](const FontIconTableEntry& a, const FontIconTableEntry& b)
|
||||||
|
{
|
||||||
|
return a.iconName < b.iconName;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextRenderer::UI_Init_Hk(const int localClientNum)
|
||||||
|
{
|
||||||
|
// Call original method
|
||||||
|
Utils::Hook::Call<void(int)>(0x4A57D0)(localClientNum);
|
||||||
|
|
||||||
|
InitFontIcons();
|
||||||
|
}
|
||||||
|
|
||||||
TextRenderer::TextRenderer()
|
TextRenderer::TextRenderer()
|
||||||
{
|
{
|
||||||
currentColorTable = &colorTableDefault;
|
currentColorTable = &colorTableDefault;
|
||||||
@ -1366,6 +1436,9 @@ namespace Components
|
|||||||
cg_fontIconAutocompleteHint = Dvar::Register<bool>("cg_fontIconAutocompleteHint", true, Game::dvar_flag::DVAR_FLAG_SAVED, "Show hint text in autocomplete for fonticons.");
|
cg_fontIconAutocompleteHint = Dvar::Register<bool>("cg_fontIconAutocompleteHint", true, Game::dvar_flag::DVAR_FLAG_SAVED, "Show hint text in autocomplete for fonticons.");
|
||||||
sv_customTextColor = Game::Dvar_RegisterColor("sv_customTextColor", 1, 0.7f, 0, 1, Game::dvar_flag::DVAR_FLAG_REPLICATED, "Color for the extended color code.");
|
sv_customTextColor = Game::Dvar_RegisterColor("sv_customTextColor", 1, 0.7f, 0, 1, Game::dvar_flag::DVAR_FLAG_REPLICATED, "Color for the extended color code.");
|
||||||
|
|
||||||
|
// Initialize font icons when initializing UI
|
||||||
|
Utils::Hook(0x4B5422, UI_Init_Hk, HOOK_CALL).install()->quick();
|
||||||
|
|
||||||
// Replace vanilla text drawing function with a reimplementation with extensions
|
// Replace vanilla text drawing function with a reimplementation with extensions
|
||||||
Utils::Hook(0x535410, DrawText2D, HOOK_JUMP).install()->quick();
|
Utils::Hook(0x535410, DrawText2D, HOOK_JUMP).install()->quick();
|
||||||
|
|
||||||
|
@ -42,6 +42,13 @@ namespace Components
|
|||||||
|
|
||||||
class TextRenderer : public Component
|
class TextRenderer : public Component
|
||||||
{
|
{
|
||||||
|
struct FontIconTableEntry
|
||||||
|
{
|
||||||
|
std::string iconName;
|
||||||
|
std::string materialName;
|
||||||
|
Game::Material* material;
|
||||||
|
};
|
||||||
|
|
||||||
struct FontIconInfo
|
struct FontIconInfo
|
||||||
{
|
{
|
||||||
Game::Material* material;
|
Game::Material* material;
|
||||||
@ -126,6 +133,8 @@ namespace Components
|
|||||||
static unsigned colorTableNew[TEXT_COLOR_COUNT];
|
static unsigned colorTableNew[TEXT_COLOR_COUNT];
|
||||||
static unsigned(*currentColorTable)[TEXT_COLOR_COUNT];
|
static unsigned(*currentColorTable)[TEXT_COLOR_COUNT];
|
||||||
static FontIconAutocompleteContext autocompleteContextArray[FONT_ICON_ACI_COUNT];
|
static FontIconAutocompleteContext autocompleteContextArray[FONT_ICON_ACI_COUNT];
|
||||||
|
static std::map<std::string, FontIconTableEntry> fontIconLookup;
|
||||||
|
static std::vector<FontIconTableEntry> fontIconList;
|
||||||
|
|
||||||
static Dvar::Var cg_newColors;
|
static Dvar::Var cg_newColors;
|
||||||
static Dvar::Var cg_fontIconAutocomplete;
|
static Dvar::Var cg_fontIconAutocomplete;
|
||||||
@ -188,5 +197,8 @@ namespace Components
|
|||||||
static float DrawHudIcon(const char*& text, float x, float y, float sinAngle, float cosAngle, const Game::Font_s* font, float xScale, float yScale, unsigned color);
|
static float DrawHudIcon(const char*& text, float x, float y, float sinAngle, float cosAngle, const Game::Font_s* font, float xScale, float yScale, unsigned color);
|
||||||
static void RotateXY(float cosAngle, float sinAngle, float pivotX, float pivotY, float x, float y, float* outX, float* outY);
|
static void RotateXY(float cosAngle, float sinAngle, float pivotX, float pivotY, float x, float y, float* outX, float* outY);
|
||||||
static void UpdateColorTable();
|
static void UpdateColorTable();
|
||||||
|
|
||||||
|
static void InitFontIcons();
|
||||||
|
static void UI_Init_Hk(int localClientNum);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user