[Deps]: Rename stb_truetype.h to stb_truetype.hpp (#719)
This commit is contained in:
parent
3ff8486fc3
commit
0d96a0882b
@ -2,7 +2,7 @@
|
|||||||
#include "IFont_s.hpp"
|
#include "IFont_s.hpp"
|
||||||
|
|
||||||
#define STB_TRUETYPE_IMPLEMENTATION
|
#define STB_TRUETYPE_IMPLEMENTATION
|
||||||
#include <stb_truetype.h>
|
#include <stb_truetype.hpp>
|
||||||
|
|
||||||
#include <json.hpp>
|
#include <json.hpp>
|
||||||
|
|
||||||
|
@ -56,6 +56,19 @@ namespace Components
|
|||||||
Game::SV_GameSendServerCommand(player - Game::g_entities, Game::SV_CMD_CAN_IGNORE, Utils::String::VA("%c \"You are muted\"", 0x65));
|
Game::SV_GameSendServerCommand(player - Game::g_entities, Game::SV_CMD_CAN_IGNORE, Utils::String::VA("%c \"You are muted\"", 0x65));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sv_disableChat.get<bool>())
|
||||||
|
{
|
||||||
|
SendChat = false;
|
||||||
|
Game::SV_GameSendServerCommand(player - Game::g_entities, Game::SV_CMD_CAN_IGNORE, Utils::String::VA("%c \"Chat is disabled\"", 0x65));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Message might be empty after processing the '/'
|
||||||
|
if (text[msgIndex] == '\0')
|
||||||
|
{
|
||||||
|
SendChat = false;
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto& callback : SayCallbacks)
|
for (const auto& callback : SayCallbacks)
|
||||||
{
|
{
|
||||||
if (!ChatCallback(player, callback.getPos(), (text + msgIndex), mode))
|
if (!ChatCallback(player, callback.getPos(), (text + msgIndex), mode))
|
||||||
@ -64,12 +77,6 @@ namespace Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sv_disableChat.get<bool>())
|
|
||||||
{
|
|
||||||
SendChat = false;
|
|
||||||
Game::SV_GameSendServerCommand(player - Game::g_entities, Game::SV_CMD_CAN_IGNORE, Utils::String::VA("%c \"Chat is disabled\"", 0x65));
|
|
||||||
}
|
|
||||||
|
|
||||||
TextRenderer::StripMaterialTextIcons(text, text, std::strlen(text) + 1);
|
TextRenderer::StripMaterialTextIcons(text, text, std::strlen(text) + 1);
|
||||||
|
|
||||||
Game::Scr_AddEntity(player);
|
Game::Scr_AddEntity(player);
|
||||||
|
@ -102,8 +102,6 @@ namespace Components
|
|||||||
|
|
||||||
const char Debug::StrTemplate[] = "%s: %s All those moments will be lost in time, like tears in rain.";
|
const char Debug::StrTemplate[] = "%s: %s All those moments will be lost in time, like tears in rain.";
|
||||||
|
|
||||||
const float Debug::ColorWhite[] = {1.0f, 1.0f, 1.0f, 1.0f};
|
|
||||||
|
|
||||||
std::string Debug::BuildPMFlagsString(const Game::playerState_s* ps)
|
std::string Debug::BuildPMFlagsString(const Game::playerState_s* ps)
|
||||||
{
|
{
|
||||||
std::string result;
|
std::string result;
|
||||||
@ -163,19 +161,19 @@ namespace Components
|
|||||||
auto* const font2 = Game::UI_GetFontHandle(scrPlace, 6, MY_SCALE2);
|
auto* const font2 = Game::UI_GetFontHandle(scrPlace, 6, MY_SCALE2);
|
||||||
|
|
||||||
Game::UI_DrawText(scrPlace, "Client View of Flags", maxChars, font2, -60.0f, 0, 1, 1,
|
Game::UI_DrawText(scrPlace, "Client View of Flags", maxChars, font2, -60.0f, 0, 1, 1,
|
||||||
MY_SCALE2, ColorWhite, 1);
|
MY_SCALE2, TextRenderer::WHITE_COLOR, 1);
|
||||||
|
|
||||||
const auto pmf = BuildPMFlagsString(&cgameGlob->predictedPlayerState);
|
const auto pmf = BuildPMFlagsString(&cgameGlob->predictedPlayerState);
|
||||||
Game::UI_DrawText(scrPlace, pmf.data(), maxChars, font1, 30.0f, MY_Y, 1, 1, MY_SCALE_2, ColorWhite, 3);
|
Game::UI_DrawText(scrPlace, pmf.data(), maxChars, font1, 30.0f, MY_Y, 1, 1, MY_SCALE_2, TextRenderer::WHITE_COLOR, 3);
|
||||||
|
|
||||||
const auto pof = BuildPOFlagsString(&cgameGlob->predictedPlayerState);
|
const auto pof = BuildPOFlagsString(&cgameGlob->predictedPlayerState);
|
||||||
Game::UI_DrawText(scrPlace, pof.data(), maxChars, font1, 350.0f, MY_Y, 1, 1, MY_SCALE_2, ColorWhite, 3);
|
Game::UI_DrawText(scrPlace, pof.data(), maxChars, font1, 350.0f, MY_Y, 1, 1, MY_SCALE_2, TextRenderer::WHITE_COLOR, 3);
|
||||||
|
|
||||||
const auto plf = BuildPLFlagsString(&cgameGlob->predictedPlayerState);
|
const auto plf = BuildPLFlagsString(&cgameGlob->predictedPlayerState);
|
||||||
Game::UI_DrawText(scrPlace, plf.data(), maxChars, font1, 350.0f, 250.0f, 1, 1, MY_SCALE_2, ColorWhite, 3);
|
Game::UI_DrawText(scrPlace, plf.data(), maxChars, font1, 350.0f, 250.0f, 1, 1, MY_SCALE_2, TextRenderer::WHITE_COLOR, 3);
|
||||||
|
|
||||||
const auto pef = BuildPEFlagsString(&cgameGlob->predictedPlayerState);
|
const auto pef = BuildPEFlagsString(&cgameGlob->predictedPlayerState);
|
||||||
Game::UI_DrawText(scrPlace, pef.data(), maxChars, font1, 525.0f, MY_Y, 1, 1, MY_SCALE_2, ColorWhite, 3);
|
Game::UI_DrawText(scrPlace, pef.data(), maxChars, font1, 525.0f, MY_Y, 1, 1, MY_SCALE_2, TextRenderer::WHITE_COLOR, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Debug::CG_DrawDebugPlayerHealth(const int localClientNum)
|
void Debug::CG_DrawDebugPlayerHealth(const int localClientNum)
|
||||||
@ -223,23 +221,23 @@ namespace Components
|
|||||||
|
|
||||||
sprintf_s(strFinal, StrTemplate, font1->fontName, StrButtons);
|
sprintf_s(strFinal, StrTemplate, font1->fontName, StrButtons);
|
||||||
Game::UI_FilterStringForButtonAnimation(strFinal, sizeof(strFinal));
|
Game::UI_FilterStringForButtonAnimation(strFinal, sizeof(strFinal));
|
||||||
Game::UI_DrawText(scrPlace, strFinal, std::numeric_limits<int>::max(), font1, MY_X, 10.0f, 1, 1, 0.4f, ColorWhite, 3);
|
Game::UI_DrawText(scrPlace, strFinal, std::numeric_limits<int>::max(), font1, MY_X, 10.0f, 1, 1, 0.4f, TextRenderer::WHITE_COLOR, 3);
|
||||||
|
|
||||||
sprintf_s(strFinal, StrTemplate, font2->fontName, StrButtons);
|
sprintf_s(strFinal, StrTemplate, font2->fontName, StrButtons);
|
||||||
Game::UI_FilterStringForButtonAnimation(strFinal, sizeof(strFinal));
|
Game::UI_FilterStringForButtonAnimation(strFinal, sizeof(strFinal));
|
||||||
Game::UI_DrawText(scrPlace, strFinal, std::numeric_limits<int>::max(), font2, MY_X, 35.0f, 1, 1, 0.4f, ColorWhite, 3);
|
Game::UI_DrawText(scrPlace, strFinal, std::numeric_limits<int>::max(), font2, MY_X, 35.0f, 1, 1, 0.4f, TextRenderer::WHITE_COLOR, 3);
|
||||||
|
|
||||||
sprintf_s(strFinal, StrTemplate, font3->fontName, StrButtons);
|
sprintf_s(strFinal, StrTemplate, font3->fontName, StrButtons);
|
||||||
Game::UI_FilterStringForButtonAnimation(strFinal, sizeof(strFinal));
|
Game::UI_FilterStringForButtonAnimation(strFinal, sizeof(strFinal));
|
||||||
Game::UI_DrawText(scrPlace, strFinal, std::numeric_limits<int>::max(), font3, MY_X, 60.0f, 1, 1, 0.4f, ColorWhite, 3);
|
Game::UI_DrawText(scrPlace, strFinal, std::numeric_limits<int>::max(), font3, MY_X, 60.0f, 1, 1, 0.4f, TextRenderer::WHITE_COLOR, 3);
|
||||||
|
|
||||||
sprintf_s(strFinal, StrTemplate, font5->fontName, StrButtons);
|
sprintf_s(strFinal, StrTemplate, font5->fontName, StrButtons);
|
||||||
Game::UI_FilterStringForButtonAnimation(strFinal, sizeof(strFinal));
|
Game::UI_FilterStringForButtonAnimation(strFinal, sizeof(strFinal));
|
||||||
Game::UI_DrawText(scrPlace, strFinal, std::numeric_limits<int>::max(), font5, MY_X, 85.0f, 1, 1, 0.4f, ColorWhite, 3);
|
Game::UI_DrawText(scrPlace, strFinal, std::numeric_limits<int>::max(), font5, MY_X, 85.0f, 1, 1, 0.4f, TextRenderer::WHITE_COLOR, 3);
|
||||||
|
|
||||||
sprintf_s(strFinal, StrTemplate, font6->fontName, StrButtons);
|
sprintf_s(strFinal, StrTemplate, font6->fontName, StrButtons);
|
||||||
Game::UI_FilterStringForButtonAnimation(strFinal, sizeof(strFinal));
|
Game::UI_FilterStringForButtonAnimation(strFinal, sizeof(strFinal));
|
||||||
Game::UI_DrawText(scrPlace, strFinal, std::numeric_limits<int>::max(), font6, MY_X, 110.0f, 1, 1, 0.4f, ColorWhite, 3);
|
Game::UI_DrawText(scrPlace, strFinal, std::numeric_limits<int>::max(), font6, MY_X, 110.0f, 1, 1, 0.4f, TextRenderer::WHITE_COLOR, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Debug::CG_DrawDebugOverlays_Hk(const int localClientNum)
|
void Debug::CG_DrawDebugOverlays_Hk(const int localClientNum)
|
||||||
|
@ -28,8 +28,6 @@ namespace Components
|
|||||||
static constexpr auto MY_X = -25.0f;
|
static constexpr auto MY_X = -25.0f;
|
||||||
static constexpr auto MY_Y = 20.0f;
|
static constexpr auto MY_Y = 20.0f;
|
||||||
|
|
||||||
static const float ColorWhite[];
|
|
||||||
|
|
||||||
static std::string BuildPMFlagsString(const Game::playerState_s* ps);
|
static std::string BuildPMFlagsString(const Game::playerState_s* ps);
|
||||||
static std::string BuildPOFlagsString(const Game::playerState_s* ps);
|
static std::string BuildPOFlagsString(const Game::playerState_s* ps);
|
||||||
static std::string BuildPLFlagsString(const Game::playerState_s* ps);
|
static std::string BuildPLFlagsString(const Game::playerState_s* ps);
|
||||||
|
@ -60,7 +60,7 @@ namespace Components
|
|||||||
Game::dvar_t* TextRenderer::g_ColorBlind_EnemyTeam;
|
Game::dvar_t* TextRenderer::g_ColorBlind_EnemyTeam;
|
||||||
Game::dvar_t** TextRenderer::con_inputBoxColor = reinterpret_cast<Game::dvar_t**>(0x9FD4BC);
|
Game::dvar_t** TextRenderer::con_inputBoxColor = reinterpret_cast<Game::dvar_t**>(0x9FD4BC);
|
||||||
|
|
||||||
TextRenderer::BufferedLocalizedString::BufferedLocalizedString(const char* reference, const size_t bufferSize)
|
TextRenderer::BufferedLocalizedString::BufferedLocalizedString(const char* reference, const std::size_t bufferSize)
|
||||||
: stringReference(reference),
|
: stringReference(reference),
|
||||||
stringBuffer(std::make_unique<char[]>(bufferSize)),
|
stringBuffer(std::make_unique<char[]>(bufferSize)),
|
||||||
stringBufferSize(bufferSize),
|
stringBufferSize(bufferSize),
|
||||||
@ -75,11 +75,13 @@ namespace Components
|
|||||||
|
|
||||||
if (formattingString != nullptr)
|
if (formattingString != nullptr)
|
||||||
{
|
{
|
||||||
strncpy(stringBuffer.get(), formattingString, stringBufferSize);
|
strncpy_s(stringBuffer.get(), stringBufferSize, formattingString, _TRUNCATE);
|
||||||
for (auto& width : stringWidth)
|
for (auto& width : stringWidth)
|
||||||
|
{
|
||||||
width = -1;
|
width = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const char* TextRenderer::BufferedLocalizedString::Format(const char* value)
|
const char* TextRenderer::BufferedLocalizedString::Format(const char* value)
|
||||||
{
|
{
|
||||||
@ -95,7 +97,10 @@ namespace Components
|
|||||||
Game::UI_ReplaceConversions(formattingString, &conversionArguments, stringBuffer.get(), stringBufferSize);
|
Game::UI_ReplaceConversions(formattingString, &conversionArguments, stringBuffer.get(), stringBufferSize);
|
||||||
|
|
||||||
for (auto& width : stringWidth)
|
for (auto& width : stringWidth)
|
||||||
|
{
|
||||||
width = -1;
|
width = -1;
|
||||||
|
}
|
||||||
|
|
||||||
return stringBuffer.get();
|
return stringBuffer.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,7 +113,9 @@ namespace Components
|
|||||||
{
|
{
|
||||||
assert(autocompleteInstance < FONT_ICON_ACI_COUNT);
|
assert(autocompleteInstance < FONT_ICON_ACI_COUNT);
|
||||||
if (stringWidth[autocompleteInstance] < 0)
|
if (stringWidth[autocompleteInstance] < 0)
|
||||||
|
{
|
||||||
stringWidth[autocompleteInstance] = Game::R_TextWidth(GetString(), std::numeric_limits<int>::max(), font);
|
stringWidth[autocompleteInstance] = Game::R_TextWidth(GetString(), std::numeric_limits<int>::max(), font);
|
||||||
|
}
|
||||||
|
|
||||||
return stringWidth[autocompleteInstance];
|
return stringWidth[autocompleteInstance];
|
||||||
}
|
}
|
||||||
@ -117,13 +124,13 @@ namespace Components
|
|||||||
: autocompleteActive(false),
|
: autocompleteActive(false),
|
||||||
inModifiers(false),
|
inModifiers(false),
|
||||||
userClosed(false),
|
userClosed(false),
|
||||||
lastHash(0u),
|
lastHash(0),
|
||||||
results{},
|
results{},
|
||||||
resultCount(0u),
|
resultCount(0),
|
||||||
hasMoreResults(false),
|
hasMoreResults(false),
|
||||||
resultOffset(0u),
|
resultOffset(0),
|
||||||
lastResultOffset(0u),
|
lastResultOffset(0),
|
||||||
selectedOffset(0u),
|
selectedOffset(0),
|
||||||
maxFontIconWidth(0.0f),
|
maxFontIconWidth(0.0f),
|
||||||
maxMaterialNameWidth(0.0f),
|
maxMaterialNameWidth(0.0f),
|
||||||
stringSearchStartWith(REFERENCE_SEARCH_START_WITH, STRING_BUFFER_SIZE_BIG)
|
stringSearchStartWith(REFERENCE_SEARCH_START_WITH, STRING_BUFFER_SIZE_BIG)
|
||||||
@ -182,13 +189,6 @@ namespace Components
|
|||||||
|
|
||||||
void TextRenderer::DrawAutocompleteBox(const FontIconAutocompleteContext& context, const float x, const float y, const float w, const float h, const float* color)
|
void TextRenderer::DrawAutocompleteBox(const FontIconAutocompleteContext& context, const float x, const float y, const float w, const float h, const float* color)
|
||||||
{
|
{
|
||||||
static constexpr float colorWhite[4]
|
|
||||||
{
|
|
||||||
1.0f,
|
|
||||||
1.0f,
|
|
||||||
1.0f,
|
|
||||||
1.0f
|
|
||||||
};
|
|
||||||
const float borderColor[4]
|
const float borderColor[4]
|
||||||
{
|
{
|
||||||
color[0] * 0.5f,
|
color[0] * 0.5f,
|
||||||
@ -209,15 +209,16 @@ namespace Components
|
|||||||
y + FONT_ICON_AUTOCOMPLETE_BOX_BORDER,
|
y + FONT_ICON_AUTOCOMPLETE_BOX_BORDER,
|
||||||
FONT_ICON_AUTOCOMPLETE_ARROW_SIZE,
|
FONT_ICON_AUTOCOMPLETE_ARROW_SIZE,
|
||||||
FONT_ICON_AUTOCOMPLETE_ARROW_SIZE,
|
FONT_ICON_AUTOCOMPLETE_ARROW_SIZE,
|
||||||
1.0f, 1.0f, 0.0f, 0.0f, colorWhite, Game::sharedUiInfo->assets.scrollBarArrowDown);
|
1.0f, 1.0f, 0.0f, 0.0f, WHITE_COLOR, Game::sharedUiInfo->assets.scrollBarArrowDown);
|
||||||
}
|
}
|
||||||
if(context.hasMoreResults)
|
|
||||||
|
if (context.hasMoreResults)
|
||||||
{
|
{
|
||||||
Game::R_AddCmdDrawStretchPic(x + w - FONT_ICON_AUTOCOMPLETE_BOX_BORDER - FONT_ICON_AUTOCOMPLETE_ARROW_SIZE,
|
Game::R_AddCmdDrawStretchPic(x + w - FONT_ICON_AUTOCOMPLETE_BOX_BORDER - FONT_ICON_AUTOCOMPLETE_ARROW_SIZE,
|
||||||
y + h - FONT_ICON_AUTOCOMPLETE_BOX_BORDER - FONT_ICON_AUTOCOMPLETE_ARROW_SIZE,
|
y + h - FONT_ICON_AUTOCOMPLETE_BOX_BORDER - FONT_ICON_AUTOCOMPLETE_ARROW_SIZE,
|
||||||
FONT_ICON_AUTOCOMPLETE_ARROW_SIZE,
|
FONT_ICON_AUTOCOMPLETE_ARROW_SIZE,
|
||||||
FONT_ICON_AUTOCOMPLETE_ARROW_SIZE,
|
FONT_ICON_AUTOCOMPLETE_ARROW_SIZE,
|
||||||
1.0f, 1.0f, 0.0f, 0.0f, colorWhite, Game::sharedUiInfo->assets.scrollBarArrowUp);
|
1.0f, 1.0f, 0.0f, 0.0f, WHITE_COLOR, Game::sharedUiInfo->assets.scrollBarArrowUp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,7 +231,7 @@ namespace Components
|
|||||||
auto skipCount = context.resultOffset;
|
auto skipCount = context.resultOffset;
|
||||||
|
|
||||||
const auto queryLen = context.lastQuery.size();
|
const auto queryLen = context.lastQuery.size();
|
||||||
for(const auto& fontIconEntry : fontIconList)
|
for (const auto& fontIconEntry : fontIconList)
|
||||||
{
|
{
|
||||||
const auto compareValue = fontIconEntry.iconName.compare(0, queryLen, context.lastQuery);
|
const auto compareValue = fontIconEntry.iconName.compare(0, queryLen, context.lastQuery);
|
||||||
|
|
||||||
@ -242,21 +243,26 @@ namespace Components
|
|||||||
}
|
}
|
||||||
else if (context.resultCount < FontIconAutocompleteContext::MAX_RESULTS)
|
else if (context.resultCount < FontIconAutocompleteContext::MAX_RESULTS)
|
||||||
{
|
{
|
||||||
context.results[context.resultCount++] = {
|
context.results[context.resultCount++] =
|
||||||
|
{
|
||||||
Utils::String::VA(":%s:", fontIconEntry.iconName.data()),
|
Utils::String::VA(":%s:", fontIconEntry.iconName.data()),
|
||||||
fontIconEntry.iconName
|
fontIconEntry.iconName
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
context.hasMoreResults = true;
|
context.hasMoreResults = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if (compareValue > 0)
|
else if (compareValue > 0)
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
context.maxFontIconWidth = 0;
|
context.maxFontIconWidth = 0;
|
||||||
context.maxMaterialNameWidth = 0;
|
context.maxMaterialNameWidth = 0;
|
||||||
for(auto resultIndex = 0u; resultIndex < context.resultCount; resultIndex++)
|
for (auto resultIndex = 0u; resultIndex < context.resultCount; resultIndex++)
|
||||||
{
|
{
|
||||||
const auto& result = context.results[resultIndex];
|
const auto& result = context.results[resultIndex];
|
||||||
const auto fontIconWidth = static_cast<float>(Game::R_TextWidth(result.fontIconName.c_str(), std::numeric_limits<int>::max(), font)) * textXScale;
|
const auto fontIconWidth = static_cast<float>(Game::R_TextWidth(result.fontIconName.c_str(), std::numeric_limits<int>::max(), font)) * textXScale;
|
||||||
@ -274,12 +280,12 @@ namespace Components
|
|||||||
int fontIconStart = -1;
|
int fontIconStart = -1;
|
||||||
auto inModifiers = false;
|
auto inModifiers = false;
|
||||||
|
|
||||||
for(auto i = 0; i < edit->cursor; i++)
|
for (auto i = 0; i < edit->cursor; i++)
|
||||||
{
|
{
|
||||||
const auto c = static_cast<unsigned char>(edit->buffer[i]);
|
const auto c = static_cast<unsigned char>(edit->buffer[i]);
|
||||||
if (c == FONT_ICON_SEPARATOR_CHARACTER)
|
if (c == FONT_ICON_SEPARATOR_CHARACTER)
|
||||||
{
|
{
|
||||||
if(fontIconStart < 0)
|
if (fontIconStart < 0)
|
||||||
{
|
{
|
||||||
fontIconStart = i + 1;
|
fontIconStart = i + 1;
|
||||||
inModifiers = false;
|
inModifiers = false;
|
||||||
@ -290,12 +296,12 @@ namespace Components
|
|||||||
inModifiers = false;
|
inModifiers = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(isspace(c))
|
else if (std::isspace(c))
|
||||||
{
|
{
|
||||||
fontIconStart = -1;
|
fontIconStart = -1;
|
||||||
inModifiers = false;
|
inModifiers = false;
|
||||||
}
|
}
|
||||||
else if(c == FONT_ICON_MODIFIER_SEPARATOR_CHARACTER)
|
else if (c == FONT_ICON_MODIFIER_SEPARATOR_CHARACTER)
|
||||||
{
|
{
|
||||||
if (fontIconStart >= 0 && !inModifiers)
|
if (fontIconStart >= 0 && !inModifiers)
|
||||||
{
|
{
|
||||||
@ -309,10 +315,10 @@ namespace Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(fontIconStart < 0 // Not in fonticon sequence
|
if (fontIconStart < 0 // Not in fonticon sequence
|
||||||
|| fontIconStart == edit->cursor // Did not type the first letter yet
|
|| fontIconStart == edit->cursor // Did not type the first letter yet
|
||||||
|| !isalpha(static_cast<unsigned char>(edit->buffer[fontIconStart])) // First letter of the icon is not alphabetic
|
|| !std::isalpha(static_cast<unsigned char>(edit->buffer[fontIconStart])) // First letter of the icon is not alphabetic
|
||||||
|| (fontIconStart > 1 && isalnum(static_cast<unsigned char>(edit->buffer[fontIconStart - 2]))) // Letter before sequence is alnum
|
|| (fontIconStart > 1 && std::isalnum(static_cast<unsigned char>(edit->buffer[fontIconStart - 2]))) // Letter before sequence is alnum
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
context.autocompleteActive = false;
|
context.autocompleteActive = false;
|
||||||
@ -325,28 +331,38 @@ namespace Components
|
|||||||
context.inModifiers = inModifiers;
|
context.inModifiers = inModifiers;
|
||||||
|
|
||||||
// Update scroll
|
// Update scroll
|
||||||
if(context.selectedOffset < context.resultOffset)
|
if (context.selectedOffset < context.resultOffset)
|
||||||
|
{
|
||||||
context.resultOffset = context.selectedOffset;
|
context.resultOffset = context.selectedOffset;
|
||||||
|
}
|
||||||
else if(context.selectedOffset >= context.resultOffset + FontIconAutocompleteContext::MAX_RESULTS)
|
else if(context.selectedOffset >= context.resultOffset + FontIconAutocompleteContext::MAX_RESULTS)
|
||||||
|
{
|
||||||
context.resultOffset = context.selectedOffset - (FontIconAutocompleteContext::MAX_RESULTS - 1);
|
context.resultOffset = context.selectedOffset - (FontIconAutocompleteContext::MAX_RESULTS - 1);
|
||||||
|
}
|
||||||
|
|
||||||
// If the user closed the context do not draw or update
|
// If the user closed the context do not draw or update
|
||||||
if (context.userClosed)
|
if (context.userClosed)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
context.autocompleteActive = true;
|
context.autocompleteActive = true;
|
||||||
|
|
||||||
// No need to update results when in modifiers
|
// No need to update results when in modifiers
|
||||||
if (context.inModifiers)
|
if (context.inModifiers)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if results need updates
|
// Check if results need updates
|
||||||
const auto currentFontIconHash = Game::R_HashString(&edit->buffer[fontIconStart], edit->cursor - fontIconStart);
|
const auto currentFontIconHash = Game::R_HashString(&edit->buffer[fontIconStart], edit->cursor - fontIconStart);
|
||||||
if (currentFontIconHash == context.lastHash && context.lastResultOffset == context.resultOffset)
|
if (currentFontIconHash == context.lastHash && context.lastResultOffset == context.resultOffset)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// If query was updated then reset scroll parameters
|
// If query was updated then reset scroll parameters
|
||||||
if(currentFontIconHash != context.lastHash)
|
if (currentFontIconHash != context.lastHash)
|
||||||
{
|
{
|
||||||
context.resultOffset = 0;
|
context.resultOffset = 0;
|
||||||
context.selectedOffset = 0;
|
context.selectedOffset = 0;
|
||||||
@ -427,7 +443,7 @@ namespace Components
|
|||||||
|
|
||||||
// Draw search results
|
// Draw search results
|
||||||
const auto selectedIndex = context.selectedOffset - context.resultOffset;
|
const auto selectedIndex = context.selectedOffset - context.resultOffset;
|
||||||
for(auto resultIndex = 0u; resultIndex < context.resultCount; resultIndex++)
|
for (auto resultIndex = 0u; resultIndex < context.resultCount; resultIndex++)
|
||||||
{
|
{
|
||||||
const auto& result = context.results[resultIndex];
|
const auto& result = context.results[resultIndex];
|
||||||
Game::R_AddCmdDrawText(result.fontIconName.c_str(), std::numeric_limits<int>::max(), font, x, currentY, textXScale, textYScale, 0.0, TEXT_COLOR, 0);
|
Game::R_AddCmdDrawText(result.fontIconName.c_str(), std::numeric_limits<int>::max(), font, x, currentY, textXScale, textYScale, 0.0, TEXT_COLOR, 0);
|
||||||
@ -440,7 +456,7 @@ namespace Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Draw extra hint if enabled
|
// Draw extra hint if enabled
|
||||||
if(hintEnabled)
|
if (hintEnabled)
|
||||||
{
|
{
|
||||||
Game::R_AddCmdDrawText(stringHintAutoComplete.GetString(), std::numeric_limits<int>::max(), font, x, currentY, textXScale, textYScale, 0.0, HINT_COLOR, 0);
|
Game::R_AddCmdDrawText(stringHintAutoComplete.GetString(), std::numeric_limits<int>::max(), font, x, currentY, textXScale, textYScale, 0.0, HINT_COLOR, 0);
|
||||||
currentY += lineHeight;
|
currentY += lineHeight;
|
||||||
@ -512,20 +528,26 @@ namespace Components
|
|||||||
void TextRenderer::AutocompleteUp(FontIconAutocompleteContext& context)
|
void TextRenderer::AutocompleteUp(FontIconAutocompleteContext& context)
|
||||||
{
|
{
|
||||||
if (context.selectedOffset > 0)
|
if (context.selectedOffset > 0)
|
||||||
|
{
|
||||||
context.selectedOffset--;
|
context.selectedOffset--;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TextRenderer::AutocompleteDown(FontIconAutocompleteContext& context)
|
void TextRenderer::AutocompleteDown(FontIconAutocompleteContext& context)
|
||||||
{
|
{
|
||||||
if (context.resultCount < FontIconAutocompleteContext::MAX_RESULTS)
|
if (context.resultCount < FontIconAutocompleteContext::MAX_RESULTS)
|
||||||
{
|
{
|
||||||
if (context.resultCount > 0 && context.selectedOffset < context.resultOffset + context.resultCount - 1)
|
if (context.resultCount > 0 && context.selectedOffset < context.resultOffset + context.resultCount - 1)
|
||||||
context.selectedOffset++;
|
{
|
||||||
|
++context.selectedOffset;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (context.selectedOffset == context.resultOffset + context.resultCount - 1)
|
else if (context.selectedOffset == context.resultOffset + context.resultCount - 1)
|
||||||
{
|
{
|
||||||
if (context.hasMoreResults)
|
if (context.hasMoreResults)
|
||||||
context.selectedOffset++;
|
{
|
||||||
|
++context.selectedOffset;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -540,15 +562,21 @@ namespace Components
|
|||||||
|
|
||||||
const auto selectedResultIndex = context.selectedOffset - context.resultOffset;
|
const auto selectedResultIndex = context.selectedOffset - context.resultOffset;
|
||||||
std::string remainingFillData = context.results[selectedResultIndex].materialName.substr(context.lastQuery.size());
|
std::string remainingFillData = context.results[selectedResultIndex].materialName.substr(context.lastQuery.size());
|
||||||
|
|
||||||
if (closeFontIcon)
|
if (closeFontIcon)
|
||||||
|
{
|
||||||
remainingFillData += ":";
|
remainingFillData += ":";
|
||||||
|
}
|
||||||
|
|
||||||
const std::string moveData(&edit->buffer[edit->cursor]);
|
const std::string moveData(&edit->buffer[edit->cursor]);
|
||||||
|
|
||||||
const auto remainingBufferCharacters = std::extent_v<decltype(Game::field_t::buffer)> - edit->cursor - moveData.size() - 1;
|
const auto remainingBufferCharacters = std::extent_v<decltype(Game::field_t::buffer)> - edit->cursor - moveData.size() - 1;
|
||||||
if(remainingFillData.size() > remainingBufferCharacters)
|
if (remainingFillData.size() > remainingBufferCharacters)
|
||||||
|
{
|
||||||
remainingFillData = remainingFillData.erase(remainingBufferCharacters);
|
remainingFillData = remainingFillData.erase(remainingBufferCharacters);
|
||||||
|
}
|
||||||
|
|
||||||
if(!remainingFillData.empty())
|
if (!remainingFillData.empty())
|
||||||
{
|
{
|
||||||
strncpy(&edit->buffer[edit->cursor], remainingFillData.c_str(), remainingFillData.size());
|
strncpy(&edit->buffer[edit->cursor], remainingFillData.c_str(), remainingFillData.size());
|
||||||
strncpy(&edit->buffer[edit->cursor + remainingFillData.size()], moveData.c_str(), moveData.size());
|
strncpy(&edit->buffer[edit->cursor + remainingFillData.size()], moveData.c_str(), moveData.size());
|
||||||
@ -609,10 +637,10 @@ namespace Components
|
|||||||
if (!autocompleteContext.autocompleteActive)
|
if (!autocompleteContext.autocompleteActive)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(autocompleteInstance == FONT_ICON_ACI_CONSOLE)
|
if (autocompleteInstance == FONT_ICON_ACI_CONSOLE)
|
||||||
return AutocompleteHandleKeyDown(autocompleteContext, key, Game::scrPlaceFull, Game::g_consoleField);
|
return AutocompleteHandleKeyDown(autocompleteContext, key, Game::scrPlaceFull, Game::g_consoleField);
|
||||||
|
|
||||||
if(autocompleteInstance == FONT_ICON_ACI_CHAT)
|
if (autocompleteInstance == FONT_ICON_ACI_CHAT)
|
||||||
return AutocompleteHandleKeyDown(autocompleteContext, key, &Game::scrPlaceView[localClientNum], &Game::playerKeys[localClientNum].chatField);
|
return AutocompleteHandleKeyDown(autocompleteContext, key, &Game::scrPlaceView[localClientNum], &Game::playerKeys[localClientNum].chatField);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -658,8 +686,10 @@ namespace Components
|
|||||||
|
|
||||||
float TextRenderer::GetMonospaceWidth(Game::Font_s* font, int rendererFlags)
|
float TextRenderer::GetMonospaceWidth(Game::Font_s* font, int rendererFlags)
|
||||||
{
|
{
|
||||||
if(rendererFlags & Game::TEXT_RENDERFLAG_FORCEMONOSPACE)
|
if (rendererFlags & Game::TEXT_RENDERFLAG_FORCEMONOSPACE)
|
||||||
|
{
|
||||||
return Game::R_GetCharacterGlyph(font, 'o')->dx;
|
return Game::R_GetCharacterGlyph(font, 'o')->dx;
|
||||||
|
}
|
||||||
|
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
@ -683,7 +713,7 @@ namespace Components
|
|||||||
unsigned TextRenderer::R_FontGetRandomLetter(const int seed)
|
unsigned TextRenderer::R_FontGetRandomLetter(const int seed)
|
||||||
{
|
{
|
||||||
static constexpr char RANDOM_CHARACTERS[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
|
static constexpr char RANDOM_CHARACTERS[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
|
||||||
return RANDOM_CHARACTERS[seed % (std::extent_v<decltype(RANDOM_CHARACTERS)> -1)];
|
return RANDOM_CHARACTERS[seed % (std::extent_v<decltype(RANDOM_CHARACTERS)> - 1)];
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextRenderer::DrawTextFxExtraCharacter(Game::Material* material, const int charIndex, const float x, const float y, const float w, const float h, const float sinAngle, const float cosAngle, const unsigned color)
|
void TextRenderer::DrawTextFxExtraCharacter(Game::Material* material, const int charIndex, const float x, const float y, const float w, const float h, const float sinAngle, const float cosAngle, const unsigned color)
|
||||||
@ -696,8 +726,10 @@ namespace Components
|
|||||||
for (auto i = 0u; i < fontIconMaterial->textureCount; i++)
|
for (auto i = 0u; i < fontIconMaterial->textureCount; i++)
|
||||||
{
|
{
|
||||||
if (fontIconMaterial->textureTable[i].nameHash == COLOR_MAP_HASH)
|
if (fontIconMaterial->textureTable[i].nameHash == COLOR_MAP_HASH)
|
||||||
|
{
|
||||||
return fontIconMaterial->textureTable[i].u.image;
|
return fontIconMaterial->textureTable[i].u.image;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -711,10 +743,10 @@ namespace Components
|
|||||||
|
|
||||||
const auto* nameEnd = curPos;
|
const auto* nameEnd = curPos;
|
||||||
|
|
||||||
if(*curPos == FONT_ICON_MODIFIER_SEPARATOR_CHARACTER)
|
if (*curPos == FONT_ICON_MODIFIER_SEPARATOR_CHARACTER)
|
||||||
{
|
{
|
||||||
auto breakArgs = false;
|
auto breakArgs = false;
|
||||||
while(!breakArgs)
|
while (!breakArgs)
|
||||||
{
|
{
|
||||||
curPos++;
|
curPos++;
|
||||||
switch(*curPos)
|
switch(*curPos)
|
||||||
@ -742,16 +774,20 @@ namespace Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (*curPos != FONT_ICON_SEPARATOR_CHARACTER)
|
if (*curPos != FONT_ICON_SEPARATOR_CHARACTER)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const std::string fontIconName(text, nameEnd - text);
|
const std::string fontIconName(text, nameEnd - text);
|
||||||
|
|
||||||
const auto foundFontIcon = fontIconLookup.find(fontIconName);
|
const auto foundFontIcon = fontIconLookup.find(fontIconName);
|
||||||
if (foundFontIcon == fontIconLookup.end())
|
if (foundFontIcon == fontIconLookup.end())
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
auto& entry = foundFontIcon->second;
|
auto& entry = foundFontIcon->second;
|
||||||
if(entry.material == nullptr)
|
if (entry.material == nullptr)
|
||||||
{
|
{
|
||||||
auto* materialEntry = Game::DB_FindXAssetEntry(Game::XAssetType::ASSET_TYPE_MATERIAL, entry.materialName.data());
|
auto* materialEntry = Game::DB_FindXAssetEntry(Game::XAssetType::ASSET_TYPE_MATERIAL, entry.materialName.data());
|
||||||
if (materialEntry == nullptr)
|
if (materialEntry == nullptr)
|
||||||
@ -760,9 +796,9 @@ namespace Components
|
|||||||
if (material == nullptr || material->techniqueSet == nullptr || material->techniqueSet->name == nullptr)
|
if (material == nullptr || material->techniqueSet == nullptr || material->techniqueSet->name == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(strcmp(material->techniqueSet->name, "2d") != 0)
|
if (std::strcmp(material->techniqueSet->name, "2d") != 0)
|
||||||
{
|
{
|
||||||
Logger::Print("^1Fonticon material '{}' does not have 2d techset!\n", material->info.name);
|
Logger::PrintError(Game::CON_CHANNEL_ERROR, "Fonticon material '{}' does not have 2d techset!\n", material->info.name);
|
||||||
material = Game::DB_FindXAssetHeader(Game::ASSET_TYPE_MATERIAL, "default").material;
|
material = Game::DB_FindXAssetHeader(Game::ASSET_TYPE_MATERIAL, "default").material;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -778,7 +814,10 @@ namespace Components
|
|||||||
{
|
{
|
||||||
const auto* colorMap = GetFontIconColorMap(fontIcon.material);
|
const auto* colorMap = GetFontIconColorMap(fontIcon.material);
|
||||||
if (colorMap == nullptr)
|
if (colorMap == nullptr)
|
||||||
return 0;
|
{
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
const auto sizeMultiplier = fontIcon.big ? 1.5f : 1.0f;
|
const auto sizeMultiplier = fontIcon.big ? 1.5f : 1.0f;
|
||||||
auto colWidth = static_cast<float>(colorMap->width);
|
auto colWidth = static_cast<float>(colorMap->width);
|
||||||
auto colHeight = static_cast<float>(colorMap->height);
|
auto colHeight = static_cast<float>(colorMap->height);
|
||||||
@ -793,7 +832,10 @@ namespace Components
|
|||||||
{
|
{
|
||||||
const auto* colorMap = GetFontIconColorMap(fontIcon.material);
|
const auto* colorMap = GetFontIconColorMap(fontIcon.material);
|
||||||
if (colorMap == nullptr)
|
if (colorMap == nullptr)
|
||||||
return 0;
|
{
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
const auto sizeMultiplier = fontIcon.big ? 1.5f : 1.0f;
|
const auto sizeMultiplier = fontIcon.big ? 1.5f : 1.0f;
|
||||||
auto colWidth = static_cast<float>(colorMap->width);
|
auto colWidth = static_cast<float>(colorMap->width);
|
||||||
auto colHeight = static_cast<float>(colorMap->height);
|
auto colHeight = static_cast<float>(colorMap->height);
|
||||||
@ -808,10 +850,12 @@ namespace Components
|
|||||||
{
|
{
|
||||||
const auto* colorMap = GetFontIconColorMap(fontIcon.material);
|
const auto* colorMap = GetFontIconColorMap(fontIcon.material);
|
||||||
if (colorMap == nullptr)
|
if (colorMap == nullptr)
|
||||||
return 0;
|
{
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
float s0, t0, s1, t1;
|
float s0, t0, s1, t1;
|
||||||
if(fontIcon.flipHorizontal)
|
if (fontIcon.flipHorizontal)
|
||||||
{
|
{
|
||||||
s0 = 1.0f;
|
s0 = 1.0f;
|
||||||
s1 = 0.0f;
|
s1 = 0.0f;
|
||||||
@ -821,7 +865,7 @@ namespace Components
|
|||||||
s0 = 0.0f;
|
s0 = 0.0f;
|
||||||
s1 = 1.0f;
|
s1 = 1.0f;
|
||||||
}
|
}
|
||||||
if(fontIcon.flipVertical)
|
if (fontIcon.flipVertical)
|
||||||
{
|
{
|
||||||
t0 = 1.0f;
|
t0 = 1.0f;
|
||||||
t1 = 0.0f;
|
t1 = 0.0f;
|
||||||
@ -831,6 +875,7 @@ namespace Components
|
|||||||
t0 = 0.0f;
|
t0 = 0.0f;
|
||||||
t1 = 1.0f;
|
t1 = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
Game::Material_Process2DTextureCoordsForAtlasing(fontIcon.material, &s0, &s1, &t0, &t1);
|
Game::Material_Process2DTextureCoordsForAtlasing(fontIcon.material, &s0, &s1, &t0, &t1);
|
||||||
const auto sizeMultiplier = fontIcon.big ? 1.5f : 1.0f;
|
const auto sizeMultiplier = fontIcon.big ? 1.5f : 1.0f;
|
||||||
|
|
||||||
@ -854,7 +899,7 @@ namespace Components
|
|||||||
{
|
{
|
||||||
float s0, s1, t0, t1;
|
float s0, s1, t0, t1;
|
||||||
|
|
||||||
if(*text == '\x01')
|
if (*text == '\x01')
|
||||||
{
|
{
|
||||||
s0 = 0.0;
|
s0 = 0.0;
|
||||||
t0 = 0.0;
|
t0 = 0.0;
|
||||||
@ -868,31 +913,40 @@ namespace Components
|
|||||||
s1 = 0.0;
|
s1 = 0.0;
|
||||||
t1 = 1.0;
|
t1 = 1.0;
|
||||||
}
|
}
|
||||||
text++;
|
|
||||||
|
++text;
|
||||||
|
|
||||||
if (*text == 0)
|
if (*text == 0)
|
||||||
return 0;
|
{
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
const auto v12 = font->pixelHeight * (*text - 16) + 16;
|
const auto v12 = font->pixelHeight * (*text - 16) + 16;
|
||||||
const auto w = static_cast<float>((((v12 >> 24) & 0x1F) + v12) >> 5) * xScale;
|
const auto w = static_cast<float>((((v12 >> 24) & 0x1F) + v12) >> 5) * xScale;
|
||||||
text++;
|
++text;
|
||||||
|
|
||||||
if (*text == 0)
|
if (*text == 0)
|
||||||
return 0;
|
{
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
const auto h = static_cast<float>((font->pixelHeight * (*text - 16) + 16) >> 5) * yScale;
|
const auto h = static_cast<float>((font->pixelHeight * (*text - 16) + 16) >> 5) * yScale;
|
||||||
text++;
|
++text;
|
||||||
|
|
||||||
if (*text == 0)
|
if (*text == 0)
|
||||||
return 0;
|
{
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
const auto materialNameLen = static_cast<uint8_t>(*text);
|
const auto materialNameLen = static_cast<uint8_t>(*text);
|
||||||
text++;
|
text++;
|
||||||
|
|
||||||
for(auto i = 0u; i < materialNameLen; i++)
|
for (auto i = 0u; i < materialNameLen; i++)
|
||||||
{
|
{
|
||||||
if (text[i] == 0)
|
if (text[i] == 0)
|
||||||
return 0;
|
{
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string materialName(text, materialNameLen);
|
const std::string materialName(text, materialNameLen);
|
||||||
@ -972,7 +1026,7 @@ namespace Components
|
|||||||
const auto startX = x - xScale * 0.5f;
|
const auto startX = x - xScale * 0.5f;
|
||||||
const auto startY = y - 0.5f * yScale;
|
const auto startY = y - 0.5f * yScale;
|
||||||
|
|
||||||
for(auto passIndex = 0u; passIndex < passCount; passIndex++)
|
for (auto passIndex = 0u; passIndex < passCount; passIndex++)
|
||||||
{
|
{
|
||||||
float xRot, yRot;
|
float xRot, yRot;
|
||||||
const char* curText = text;
|
const char* curText = text;
|
||||||
@ -986,7 +1040,7 @@ namespace Components
|
|||||||
auto xa = startX;
|
auto xa = startX;
|
||||||
auto xy = startY;
|
auto xy = startY;
|
||||||
|
|
||||||
while(*curText && maxLengthRemaining)
|
while (*curText && maxLengthRemaining)
|
||||||
{
|
{
|
||||||
if (passes[passIndex] == Game::FONTPASS_NORMAL && renderFlags & Game::TEXT_RENDERFLAG_CURSOR && count == cursorPos)
|
if (passes[passIndex] == Game::FONTPASS_NORMAL && renderFlags & Game::TEXT_RENDERFLAG_CURSOR && count == cursorPos)
|
||||||
{
|
{
|
||||||
@ -996,7 +1050,7 @@ namespace Components
|
|||||||
|
|
||||||
auto letter = Game::SEH_ReadCharFromString(&curText, nullptr);
|
auto letter = Game::SEH_ReadCharFromString(&curText, nullptr);
|
||||||
|
|
||||||
if(letter == '^' && *curText >= COLOR_FIRST_CHAR && *curText <= COLOR_LAST_CHAR)
|
if (letter == '^' && *curText >= COLOR_FIRST_CHAR && *curText <= COLOR_LAST_CHAR)
|
||||||
{
|
{
|
||||||
const auto colorIndex = ColorIndexForChar(*curText);
|
const auto colorIndex = ColorIndexForChar(*curText);
|
||||||
subtitleAllowGlow = false;
|
subtitleAllowGlow = false;
|
||||||
@ -1018,7 +1072,7 @@ namespace Components
|
|||||||
currentColor.packed = ColorRgba(colorTableColor.array[2], colorTableColor.array[1], colorTableColor.array[0], color.array[3]);
|
currentColor.packed = ColorRgba(colorTableColor.array[2], colorTableColor.array[1], colorTableColor.array[0], color.array[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!(renderFlags & Game::TEXT_RENDERFLAG_CURSOR && cursorPos > count && cursorPos < count + 2))
|
if (!(renderFlags & Game::TEXT_RENDERFLAG_CURSOR && cursorPos > count && cursorPos < count + 2))
|
||||||
{
|
{
|
||||||
curText++;
|
curText++;
|
||||||
count += 2;
|
count += 2;
|
||||||
@ -1028,7 +1082,7 @@ namespace Components
|
|||||||
|
|
||||||
auto finalColor = currentColor;
|
auto finalColor = currentColor;
|
||||||
|
|
||||||
if(letter == '^' && (*curText == '\x01' || *curText == '\x02'))
|
if (letter == '^' && (*curText == '\x01' || *curText == '\x02'))
|
||||||
{
|
{
|
||||||
RotateXY(cosAngle, sinAngle, startX, startY, xa, xy, &xRot, &yRot);
|
RotateXY(cosAngle, sinAngle, startX, startY, xa, xy, &xRot, &yRot);
|
||||||
xa += DrawHudIcon(curText, xRot, yRot, sinAngle, cosAngle, font, xScale, yScale, ColorRgba(255, 255, 255, finalColor.array[3]));
|
xa += DrawHudIcon(curText, xRot, yRot, sinAngle, cosAngle, font, xScale, yScale, ColorRgba(255, 255, 255, finalColor.array[3]));
|
||||||
@ -1040,11 +1094,11 @@ namespace Components
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(letter == FONT_ICON_SEPARATOR_CHARACTER)
|
if (letter == FONT_ICON_SEPARATOR_CHARACTER)
|
||||||
{
|
{
|
||||||
FontIconInfo fontIconInfo{};
|
FontIconInfo fontIconInfo{};
|
||||||
const char* fontIconEnd = curText;
|
const char* fontIconEnd = curText;
|
||||||
if(IsFontIcon(fontIconEnd, fontIconInfo) && !(renderFlags & Game::TEXT_RENDERFLAG_CURSOR && cursorPos > count && cursorPos <= count + (fontIconEnd - curText)))
|
if (IsFontIcon(fontIconEnd, fontIconInfo) && !(renderFlags & Game::TEXT_RENDERFLAG_CURSOR && cursorPos > count && cursorPos <= count + (fontIconEnd - curText)))
|
||||||
{
|
{
|
||||||
RotateXY(cosAngle, sinAngle, startX, startY, xa, xy, &xRot, &yRot);
|
RotateXY(cosAngle, sinAngle, startX, startY, xa, xy, &xRot, &yRot);
|
||||||
|
|
||||||
@ -1062,7 +1116,7 @@ namespace Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(drawRandomCharAtEnd && maxLengthRemaining == 1)
|
if (drawRandomCharAtEnd && maxLengthRemaining == 1)
|
||||||
{
|
{
|
||||||
letter = R_FontGetRandomLetter(Game::RandWithSeed(&passRandSeed));
|
letter = R_FontGetRandomLetter(Game::RandWithSeed(&passRandSeed));
|
||||||
|
|
||||||
@ -1073,28 +1127,28 @@ namespace Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(letter == '\n')
|
if (letter == '\n')
|
||||||
{
|
{
|
||||||
xa = startX;
|
xa = startX;
|
||||||
xy += static_cast<float>(font->pixelHeight) * yScale;
|
xy += static_cast<float>(font->pixelHeight) * yScale;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(letter == '\r')
|
if (letter == '\r')
|
||||||
{
|
{
|
||||||
xy += static_cast<float>(font->pixelHeight) * yScale;
|
xy += static_cast<float>(font->pixelHeight) * yScale;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto skipDrawing = false;
|
auto skipDrawing = false;
|
||||||
if(decaying)
|
if (decaying)
|
||||||
{
|
{
|
||||||
char decayAlpha;
|
char decayAlpha;
|
||||||
Game::GetDecayingLetterInfo(letter, &passRandSeed, decayTimeElapsed, fxBirthTime, fxDecayDuration, currentColor.array[3], &skipDrawing, &decayAlpha, &letter, &drawExtraFxChar);
|
Game::GetDecayingLetterInfo(letter, &passRandSeed, decayTimeElapsed, fxBirthTime, fxDecayDuration, currentColor.array[3], &skipDrawing, &decayAlpha, &letter, &drawExtraFxChar);
|
||||||
finalColor.array[3] = decayAlpha;
|
finalColor.array[3] = decayAlpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(drawExtraFxChar)
|
if (drawExtraFxChar)
|
||||||
{
|
{
|
||||||
auto tempSeed = passRandSeed;
|
auto tempSeed = passRandSeed;
|
||||||
extraFxChar = Game::RandWithSeed(&tempSeed);
|
extraFxChar = Game::RandWithSeed(&tempSeed);
|
||||||
@ -1104,7 +1158,7 @@ namespace Components
|
|||||||
auto xAdj = static_cast<float>(glyph->x0) * xScale;
|
auto xAdj = static_cast<float>(glyph->x0) * xScale;
|
||||||
auto yAdj = static_cast<float>(glyph->y0) * yScale;
|
auto yAdj = static_cast<float>(glyph->y0) * yScale;
|
||||||
|
|
||||||
if(!skipDrawing)
|
if (!skipDrawing)
|
||||||
{
|
{
|
||||||
if (passes[passIndex] == Game::FONTPASS_NORMAL)
|
if (passes[passIndex] == Game::FONTPASS_NORMAL)
|
||||||
{
|
{
|
||||||
@ -1129,7 +1183,7 @@ namespace Components
|
|||||||
else
|
else
|
||||||
Game::RB_DrawChar(material, xRot, yRot, static_cast<float>(glyph->pixelWidth) * xScale, static_cast<float>(glyph->pixelHeight) * yScale, sinAngle, cosAngle, glyph, finalColor.packed);
|
Game::RB_DrawChar(material, xRot, yRot, static_cast<float>(glyph->pixelWidth) * xScale, static_cast<float>(glyph->pixelHeight) * yScale, sinAngle, cosAngle, glyph, finalColor.packed);
|
||||||
}
|
}
|
||||||
else if(passes[passIndex] == Game::FONTPASS_OUTLINE)
|
else if (passes[passIndex] == Game::FONTPASS_OUTLINE)
|
||||||
{
|
{
|
||||||
auto outlineSize = 1.0f;
|
auto outlineSize = 1.0f;
|
||||||
if (renderFlags & Game::TEXT_RENDERFLAG_OUTLINE_EXTRA)
|
if (renderFlags & Game::TEXT_RENDERFLAG_OUTLINE_EXTRA)
|
||||||
@ -1159,7 +1213,7 @@ namespace Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(forceMonospace)
|
if (forceMonospace)
|
||||||
xa += monospaceWidth * xScale;
|
xa += monospaceWidth * xScale;
|
||||||
else
|
else
|
||||||
xa += static_cast<float>(glyph->dx) * xScale;
|
xa += static_cast<float>(glyph->dx) * xScale;
|
||||||
@ -1171,7 +1225,7 @@ namespace Components
|
|||||||
maxLengthRemaining--;
|
maxLengthRemaining--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(renderFlags & Game::TEXT_RENDERFLAG_CURSOR && count == cursorPos)
|
if (renderFlags & Game::TEXT_RENDERFLAG_CURSOR && count == cursorPos)
|
||||||
{
|
{
|
||||||
RotateXY(cosAngle, sinAngle, startX, startY, xa, xy, &xRot, &yRot);
|
RotateXY(cosAngle, sinAngle, startX, startY, xa, xy, &xRot, &yRot);
|
||||||
Game::RB_DrawCursor(material, cursorLetter, xRot, yRot, sinAngle, cosAngle, font, xScale, yScale, color.packed);
|
Game::RB_DrawCursor(material, cursorLetter, xRot, yRot, sinAngle, cosAngle, font, xScale, yScale, color.packed);
|
||||||
@ -1220,11 +1274,15 @@ namespace Components
|
|||||||
|
|
||||||
lineWidth += w;
|
lineWidth += w;
|
||||||
if (lineWidth > maxWidth)
|
if (lineWidth > maxWidth)
|
||||||
|
{
|
||||||
maxWidth = lineWidth;
|
maxWidth = lineWidth;
|
||||||
|
}
|
||||||
|
|
||||||
text += 4;
|
text += 4;
|
||||||
for (auto currentLength = 0; currentLength < materialNameLength && *text; currentLength++)
|
for (auto currentLength = 0; currentLength < materialNameLength && *text; currentLength++)
|
||||||
text++;
|
{
|
||||||
|
++text;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1237,7 +1295,9 @@ namespace Components
|
|||||||
{
|
{
|
||||||
lineWidth += static_cast<int>(GetFontIconWidth(fontIconInfo, font, 1.0f));
|
lineWidth += static_cast<int>(GetFontIconWidth(fontIconInfo, font, 1.0f));
|
||||||
if (lineWidth > maxWidth)
|
if (lineWidth > maxWidth)
|
||||||
|
{
|
||||||
maxWidth = lineWidth;
|
maxWidth = lineWidth;
|
||||||
|
}
|
||||||
text = fontIconEnd;
|
text = fontIconEnd;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1245,7 +1305,9 @@ namespace Components
|
|||||||
|
|
||||||
lineWidth += R_GetCharacterGlyph(font, letter)->dx;
|
lineWidth += R_GetCharacterGlyph(font, letter)->dx;
|
||||||
if (lineWidth > maxWidth)
|
if (lineWidth > maxWidth)
|
||||||
|
{
|
||||||
maxWidth = lineWidth;
|
maxWidth = lineWidth;
|
||||||
|
}
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1289,15 +1351,15 @@ namespace Components
|
|||||||
{
|
{
|
||||||
char buffer[1024]{}; // 1024 is a lucky number in the engine
|
char buffer[1024]{}; // 1024 is a lucky number in the engine
|
||||||
StripColors(in.data(), buffer, sizeof(buffer));
|
StripColors(in.data(), buffer, sizeof(buffer));
|
||||||
return std::string(buffer);
|
return {buffer};
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextRenderer::StripMaterialTextIcons(const char* in, char* out, std::size_t max)
|
void TextRenderer::StripMaterialTextIcons(const char* in, char* out, std::size_t max)
|
||||||
{
|
{
|
||||||
if (!in || !out) return;
|
if (!in || !out) return;
|
||||||
|
|
||||||
max--;
|
--max;
|
||||||
size_t current = 0;
|
std::size_t current = 0;
|
||||||
while (*in != 0 && current < max)
|
while (*in != 0 && current < max)
|
||||||
{
|
{
|
||||||
if (*in == '^' && (in[1] == '\x01' || in[1] == '\x02'))
|
if (*in == '^' && (in[1] == '\x01' || in[1] == '\x02'))
|
||||||
@ -1305,18 +1367,25 @@ namespace Components
|
|||||||
in += 2;
|
in += 2;
|
||||||
|
|
||||||
if (*in) // width
|
if (*in) // width
|
||||||
in++;
|
{
|
||||||
if (*in) // height
|
++in;
|
||||||
in++;
|
}
|
||||||
|
|
||||||
if(*in) // material name length + material name characters
|
if (*in) // height
|
||||||
|
{
|
||||||
|
++in;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*in) // material name length + material name characters
|
||||||
{
|
{
|
||||||
const auto materialNameLength = *in;
|
const auto materialNameLength = *in;
|
||||||
in++;
|
++in;
|
||||||
for(auto i = 0; i < materialNameLength; i++)
|
for (auto i = 0; i < materialNameLength; i++)
|
||||||
{
|
{
|
||||||
if (*in)
|
if (*in)
|
||||||
in++;
|
{
|
||||||
|
++in;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1334,16 +1403,16 @@ namespace Components
|
|||||||
|
|
||||||
std::string TextRenderer::StripMaterialTextIcons(const std::string& in)
|
std::string TextRenderer::StripMaterialTextIcons(const std::string& in)
|
||||||
{
|
{
|
||||||
char buffer[1000] = { 0 }; // Should be more than enough
|
char buffer[1000]{}; // Should be more than enough
|
||||||
StripAllTextIcons(in.data(), buffer, sizeof(buffer));
|
StripAllTextIcons(in.data(), buffer, sizeof(buffer));
|
||||||
return std::string(buffer);
|
return {buffer};
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextRenderer::StripAllTextIcons(const char* in, char* out, std::size_t max)
|
void TextRenderer::StripAllTextIcons(const char* in, char* out, std::size_t max)
|
||||||
{
|
{
|
||||||
if (!in || !out) return;
|
if (!in || !out) return;
|
||||||
|
|
||||||
max--;
|
--max;
|
||||||
size_t current = 0;
|
size_t current = 0;
|
||||||
while (*in != 0 && current < max)
|
while (*in != 0 && current < max)
|
||||||
{
|
{
|
||||||
@ -1392,15 +1461,17 @@ namespace Components
|
|||||||
|
|
||||||
std::string TextRenderer::StripAllTextIcons(const std::string& in)
|
std::string TextRenderer::StripAllTextIcons(const std::string& in)
|
||||||
{
|
{
|
||||||
char buffer[1000] = { 0 }; // Should be more than enough
|
char buffer[1000]{}; // Should be more than enough
|
||||||
StripAllTextIcons(in.data(), buffer, sizeof(buffer));
|
StripAllTextIcons(in.data(), buffer, sizeof(buffer));
|
||||||
return std::string(buffer);
|
return {buffer};
|
||||||
}
|
}
|
||||||
|
|
||||||
int TextRenderer::SEH_PrintStrlenWithCursor(const char* string, const Game::field_t* field)
|
int TextRenderer::SEH_PrintStrlenWithCursor(const char* string, const Game::field_t* field)
|
||||||
{
|
{
|
||||||
if (!string)
|
if (!string)
|
||||||
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
const auto cursorPos = field->cursor;
|
const auto cursorPos = field->cursor;
|
||||||
auto len = 0;
|
auto len = 0;
|
||||||
@ -1481,7 +1552,8 @@ namespace Components
|
|||||||
expandedColor[3] = static_cast<float>(colorblindEnemy[3]) / 255.0f;
|
expandedColor[3] = static_cast<float>(colorblindEnemy[3]) / 255.0f;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (str == "g_TeamColor_MyTeam")
|
|
||||||
|
if (str == "g_TeamColor_MyTeam")
|
||||||
{
|
{
|
||||||
// Dvar_GetUnpackedColor
|
// Dvar_GetUnpackedColor
|
||||||
const auto* colorblindAlly = g_ColorBlind_MyTeam->current.color;
|
const auto* colorblindAlly = g_ColorBlind_MyTeam->current.color;
|
||||||
@ -1550,14 +1622,14 @@ namespace Components
|
|||||||
|
|
||||||
const auto fontIconTable = Game::DB_FindXAssetHeader(Game::ASSET_TYPE_STRINGTABLE, "mp/fonticons.csv").stringTable;
|
const auto fontIconTable = Game::DB_FindXAssetHeader(Game::ASSET_TYPE_STRINGTABLE, "mp/fonticons.csv").stringTable;
|
||||||
|
|
||||||
if(fontIconTable->columnCount < 2 || fontIconTable->rowCount <= 0)
|
if (fontIconTable->columnCount < 2 || fontIconTable->rowCount <= 0)
|
||||||
{
|
{
|
||||||
Logger::Print("^1Failed to load font icon table\n");
|
Logger::Error(Game::ERR_FATAL, "\x15" "Failed to load mp/fonticons.csv");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fontIconList.reserve(fontIconTable->rowCount);
|
fontIconList.reserve(fontIconTable->rowCount);
|
||||||
for(auto rowIndex = 0; rowIndex < fontIconTable->rowCount; rowIndex++)
|
for (auto rowIndex = 0; rowIndex < fontIconTable->rowCount; rowIndex++)
|
||||||
{
|
{
|
||||||
const auto* columns = &fontIconTable->values[rowIndex * fontIconTable->columnCount];
|
const auto* columns = &fontIconTable->values[rowIndex * fontIconTable->columnCount];
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ namespace Components
|
|||||||
|
|
||||||
class TextRenderer : public Component
|
class TextRenderer : public Component
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
static constexpr auto STRING_BUFFER_SIZE_BIG = 1024;
|
static constexpr auto STRING_BUFFER_SIZE_BIG = 1024;
|
||||||
static constexpr auto STRING_BUFFER_SIZE_SMALL = 128;
|
static constexpr auto STRING_BUFFER_SIZE_SMALL = 128;
|
||||||
|
|
||||||
@ -88,7 +89,6 @@ namespace Components
|
|||||||
1.0f
|
1.0f
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
|
||||||
static constexpr char FONT_ICON_SEPARATOR_CHARACTER = ':';
|
static constexpr char FONT_ICON_SEPARATOR_CHARACTER = ':';
|
||||||
static constexpr char FONT_ICON_MODIFIER_SEPARATOR_CHARACTER = '+';
|
static constexpr char FONT_ICON_MODIFIER_SEPARATOR_CHARACTER = '+';
|
||||||
static constexpr char FONT_ICON_MODIFIER_FLIP_HORIZONTALLY = 'h';
|
static constexpr char FONT_ICON_MODIFIER_FLIP_HORIZONTALLY = 'h';
|
||||||
@ -139,7 +139,7 @@ namespace Components
|
|||||||
class BufferedLocalizedString
|
class BufferedLocalizedString
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BufferedLocalizedString(const char* reference, size_t bufferSize);
|
BufferedLocalizedString(const char* reference, std::size_t bufferSize);
|
||||||
void Cache();
|
void Cache();
|
||||||
const char* Format(const char* value);
|
const char* Format(const char* value);
|
||||||
const char* GetString() const;
|
const char* GetString() const;
|
||||||
@ -148,7 +148,7 @@ namespace Components
|
|||||||
private:
|
private:
|
||||||
const char* stringReference;
|
const char* stringReference;
|
||||||
std::unique_ptr<char[]> stringBuffer;
|
std::unique_ptr<char[]> stringBuffer;
|
||||||
size_t stringBufferSize;
|
std::size_t stringBufferSize;
|
||||||
int stringWidth[FONT_ICON_ACI_COUNT];
|
int stringWidth[FONT_ICON_ACI_COUNT];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user