Rewrite fonticon localized string caching to fix strings being reallocated
This commit is contained in:
parent
e70b329614
commit
70bc28ee7b
@ -40,17 +40,16 @@ 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::map<std::string, TextRenderer::FontIconTableEntry> TextRenderer::fontIconLookup;
|
||||||
std::vector<TextRenderer::FontIconTableEntry> TextRenderer::fontIconList;
|
std::vector<TextRenderer::FontIconTableEntry> TextRenderer::fontIconList;
|
||||||
|
|
||||||
TextRenderer::FormattedStringBuffer<TextRenderer::STRING_BUFFER_SIZE_BIG> TextRenderer::stringSearchStartWith;
|
TextRenderer::BufferedLocalizedString TextRenderer::stringHintAutoComplete(REFERENCE_HINT_AUTO_COMPLETE, STRING_BUFFER_SIZE_SMALL);
|
||||||
TextRenderer::FormattedStringBuffer<TextRenderer::STRING_BUFFER_SIZE_SMALL> TextRenderer::stringHintAutoComplete;
|
TextRenderer::BufferedLocalizedString TextRenderer::stringHintModifier(REFERENCE_HINT_MODIFIER, STRING_BUFFER_SIZE_SMALL);
|
||||||
TextRenderer::FormattedStringBuffer<TextRenderer::STRING_BUFFER_SIZE_SMALL> TextRenderer::stringHintModifier;
|
TextRenderer::BufferedLocalizedString TextRenderer::stringListHeader(REFERENCE_MODIFIER_LIST_HEADER, STRING_BUFFER_SIZE_SMALL);
|
||||||
TextRenderer::FormattedStringBuffer<TextRenderer::STRING_BUFFER_SIZE_NONE> TextRenderer::stringListHeader;
|
TextRenderer::BufferedLocalizedString TextRenderer::stringListFlipHorizontal(REFERENCE_MODIFIER_LIST_FLIP_HORIZONTAL, STRING_BUFFER_SIZE_SMALL);
|
||||||
TextRenderer::FormattedStringBuffer<TextRenderer::STRING_BUFFER_SIZE_SMALL> TextRenderer::stringListFlipHorizontal;
|
TextRenderer::BufferedLocalizedString TextRenderer::stringListFlipVertical(REFERENCE_MODIFIER_LIST_FLIP_VERTICAL, STRING_BUFFER_SIZE_SMALL);
|
||||||
TextRenderer::FormattedStringBuffer<TextRenderer::STRING_BUFFER_SIZE_SMALL> TextRenderer::stringListFlipVertical;
|
TextRenderer::BufferedLocalizedString TextRenderer::stringListBig(REFERENCE_MODIFIER_LIST_BIG, STRING_BUFFER_SIZE_SMALL);
|
||||||
TextRenderer::FormattedStringBuffer<TextRenderer::STRING_BUFFER_SIZE_SMALL> TextRenderer::stringListBig;
|
|
||||||
|
|
||||||
Dvar::Var TextRenderer::cg_newColors;
|
Dvar::Var TextRenderer::cg_newColors;
|
||||||
Dvar::Var TextRenderer::cg_fontIconAutocomplete;
|
Dvar::Var TextRenderer::cg_fontIconAutocomplete;
|
||||||
@ -61,6 +60,77 @@ 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)
|
||||||
|
: stringReference(reference),
|
||||||
|
stringBuffer(std::make_unique<char[]>(bufferSize)),
|
||||||
|
stringBufferSize(bufferSize),
|
||||||
|
stringWidth{-1}
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextRenderer::BufferedLocalizedString::Cache()
|
||||||
|
{
|
||||||
|
const auto* formattingString = Game::UI_SafeTranslateString(stringReference);
|
||||||
|
|
||||||
|
if (formattingString != nullptr)
|
||||||
|
{
|
||||||
|
strncpy(stringBuffer.get(), formattingString, stringBufferSize);
|
||||||
|
for (auto& width : stringWidth)
|
||||||
|
width = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* TextRenderer::BufferedLocalizedString::Format(const char* value)
|
||||||
|
{
|
||||||
|
const auto* formattingString = Game::UI_SafeTranslateString(stringReference);
|
||||||
|
if (formattingString == nullptr)
|
||||||
|
{
|
||||||
|
stringBuffer[0] = '\0';
|
||||||
|
return stringBuffer.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
Game::ConversionArguments conversionArguments{};
|
||||||
|
conversionArguments.args[conversionArguments.argCount++] = value;
|
||||||
|
Game::UI_ReplaceConversions(formattingString, &conversionArguments, stringBuffer.get(), stringBufferSize);
|
||||||
|
|
||||||
|
for (auto& width : stringWidth)
|
||||||
|
width = -1;
|
||||||
|
return stringBuffer.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* TextRenderer::BufferedLocalizedString::GetString() const
|
||||||
|
{
|
||||||
|
return stringBuffer.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
int TextRenderer::BufferedLocalizedString::GetWidth(const FontIconAutocompleteInstance autocompleteInstance, Game::Font_s* font)
|
||||||
|
{
|
||||||
|
assert(autocompleteInstance < FONT_ICON_ACI_COUNT);
|
||||||
|
if (stringWidth[autocompleteInstance] < 0)
|
||||||
|
stringWidth[autocompleteInstance] = Game::R_TextWidth(GetString(), std::numeric_limits<int>::max(), font);
|
||||||
|
|
||||||
|
return stringWidth[autocompleteInstance];
|
||||||
|
}
|
||||||
|
|
||||||
|
TextRenderer::FontIconAutocompleteContext::FontIconAutocompleteContext()
|
||||||
|
: autocompleteActive(false),
|
||||||
|
inModifiers(false),
|
||||||
|
userClosed(false),
|
||||||
|
lastHash(0u),
|
||||||
|
results{},
|
||||||
|
resultCount(0u),
|
||||||
|
hasMoreResults(false),
|
||||||
|
resultOffset(0u),
|
||||||
|
lastResultOffset(0u),
|
||||||
|
selectedOffset(0u),
|
||||||
|
maxFontIconWidth(0.0f),
|
||||||
|
maxMaterialNameWidth(0.0f),
|
||||||
|
stringSearchStartWith(REFERENCE_SEARCH_START_WITH, STRING_BUFFER_SIZE_BIG)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
unsigned TextRenderer::HsvToRgb(HsvColor hsv)
|
unsigned TextRenderer::HsvToRgb(HsvColor hsv)
|
||||||
{
|
{
|
||||||
unsigned rgb;
|
unsigned rgb;
|
||||||
@ -199,7 +269,7 @@ namespace Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextRenderer::UpdateAutocompleteContext(TextRenderer::FontIconAutocompleteContext& context, const Game::field_t* edit, Game::Font_s* font, const float textXScale)
|
void TextRenderer::UpdateAutocompleteContext(FontIconAutocompleteContext& context, const Game::field_t* edit, Game::Font_s* font, const float textXScale)
|
||||||
{
|
{
|
||||||
int fontIconStart = -1;
|
int fontIconStart = -1;
|
||||||
auto inModifiers = false;
|
auto inModifiers = false;
|
||||||
@ -283,18 +353,24 @@ namespace Components
|
|||||||
context.lastHash = currentFontIconHash;
|
context.lastHash = currentFontIconHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update results for query and scroll
|
// Update results for query and scroll and update search string
|
||||||
context.lastQuery = std::string(&edit->buffer[fontIconStart], edit->cursor - fontIconStart);
|
context.lastQuery = std::string(&edit->buffer[fontIconStart], edit->cursor - fontIconStart);
|
||||||
stringSearchStartWith.Format(context.lastQuery.c_str());
|
context.stringSearchStartWith.Format(context.lastQuery.c_str());
|
||||||
UpdateAutocompleteContextResults(context, font, textXScale);
|
UpdateAutocompleteContextResults(context, font, textXScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextRenderer::DrawAutocompleteModifiers(const FontIconAutocompleteContext& context, const float x, const float y, Game::Font_s* font, float textXScale, float textYScale)
|
void TextRenderer::DrawAutocompleteModifiers(const FontIconAutocompleteInstance instance, const float x, const float y, Game::Font_s* font, const float textXScale, const float textYScale)
|
||||||
{
|
{
|
||||||
const auto textWidth = std::max(std::max(std::max(stringListHeader.GetWidth(font), stringListFlipHorizontal.GetWidth(font)),
|
assert(instance < FONT_ICON_ACI_COUNT);
|
||||||
stringListFlipVertical.GetWidth(font)),
|
const auto& context = autocompleteContextArray[instance];
|
||||||
stringListBig.GetWidth(font));
|
|
||||||
const auto boxWidth = static_cast<float>(textWidth) * textXScale;
|
// Check which is the longest string to be able to calculate how big the box needs to be
|
||||||
|
const auto longestStringLength = std::max(std::max(std::max(stringListHeader.GetWidth(instance, font), stringListFlipHorizontal.GetWidth(instance, font)),
|
||||||
|
stringListFlipVertical.GetWidth(instance, font)),
|
||||||
|
stringListBig.GetWidth(instance, font));
|
||||||
|
|
||||||
|
// Draw background box
|
||||||
|
const auto boxWidth = static_cast<float>(longestStringLength) * textXScale;
|
||||||
constexpr auto totalLines = 4u;
|
constexpr auto totalLines = 4u;
|
||||||
const auto lineHeight = static_cast<float>(font->pixelHeight) * textYScale;
|
const auto lineHeight = static_cast<float>(font->pixelHeight) * textYScale;
|
||||||
DrawAutocompleteBox(context,
|
DrawAutocompleteBox(context,
|
||||||
@ -306,8 +382,11 @@ namespace Components
|
|||||||
|
|
||||||
auto currentY = y + lineHeight;
|
auto currentY = y + lineHeight;
|
||||||
|
|
||||||
|
// Draw header line: "Following modifiers are available:"
|
||||||
Game::R_AddCmdDrawText(stringListHeader.GetString(), std::numeric_limits<int>::max(), font, x, currentY, textXScale, textYScale, 0.0, TEXT_COLOR, 0);
|
Game::R_AddCmdDrawText(stringListHeader.GetString(), std::numeric_limits<int>::max(), font, x, currentY, textXScale, textYScale, 0.0, TEXT_COLOR, 0);
|
||||||
currentY += lineHeight;
|
currentY += lineHeight;
|
||||||
|
|
||||||
|
// Draw modifier hints
|
||||||
Game::R_AddCmdDrawText(stringListFlipHorizontal.GetString(), std::numeric_limits<int>::max(), font, x, currentY, textXScale, textYScale, 0.0, TEXT_COLOR, 0);
|
Game::R_AddCmdDrawText(stringListFlipHorizontal.GetString(), std::numeric_limits<int>::max(), font, x, currentY, textXScale, textYScale, 0.0, TEXT_COLOR, 0);
|
||||||
currentY += lineHeight;
|
currentY += lineHeight;
|
||||||
Game::R_AddCmdDrawText(stringListFlipVertical.GetString(), std::numeric_limits<int>::max(), font, x, currentY, textXScale, textYScale, 0.0, TEXT_COLOR, 0);
|
Game::R_AddCmdDrawText(stringListFlipVertical.GetString(), std::numeric_limits<int>::max(), font, x, currentY, textXScale, textYScale, 0.0, TEXT_COLOR, 0);
|
||||||
@ -315,18 +394,23 @@ namespace Components
|
|||||||
Game::R_AddCmdDrawText(stringListBig.GetString(), std::numeric_limits<int>::max(), font, x, currentY, textXScale, textYScale, 0.0, TEXT_COLOR, 0);
|
Game::R_AddCmdDrawText(stringListBig.GetString(), std::numeric_limits<int>::max(), font, x, currentY, textXScale, textYScale, 0.0, TEXT_COLOR, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextRenderer::DrawAutocompleteResults(const FontIconAutocompleteContext& context, const float x, const float y, Game::Font_s* font, const float textXScale, const float textYScale)
|
void TextRenderer::DrawAutocompleteResults(const FontIconAutocompleteInstance instance, const float x, const float y, Game::Font_s* font, const float textXScale, const float textYScale)
|
||||||
{
|
{
|
||||||
|
assert(instance < FONT_ICON_ACI_COUNT);
|
||||||
|
auto& context = autocompleteContextArray[instance];
|
||||||
|
|
||||||
const auto hintEnabled = cg_fontIconAutocompleteHint.get<bool>();
|
const auto hintEnabled = cg_fontIconAutocompleteHint.get<bool>();
|
||||||
|
|
||||||
auto longestStringLength = stringSearchStartWith.GetWidth(font);
|
// Check which is the longest string to be able to calculate how big the box needs to be
|
||||||
|
auto longestStringLength = context.stringSearchStartWith.GetWidth(instance, font);
|
||||||
if(hintEnabled)
|
if(hintEnabled)
|
||||||
longestStringLength = std::max(std::max(longestStringLength, stringHintAutoComplete.GetWidth(font)), stringHintModifier.GetWidth(font));
|
longestStringLength = std::max(std::max(longestStringLength, stringHintAutoComplete.GetWidth(instance, font)), stringHintModifier.GetWidth(instance, font));
|
||||||
|
|
||||||
const auto colSpacing = FONT_ICON_AUTOCOMPLETE_COL_SPACING * textXScale;
|
const auto colSpacing = FONT_ICON_AUTOCOMPLETE_COL_SPACING * textXScale;
|
||||||
const auto boxWidth = std::max(context.maxFontIconWidth + context.maxMaterialNameWidth + colSpacing, static_cast<float>(longestStringLength) * textXScale);
|
const auto boxWidth = std::max(context.maxFontIconWidth + context.maxMaterialNameWidth + colSpacing, static_cast<float>(longestStringLength) * textXScale);
|
||||||
const auto lineHeight = static_cast<float>(font->pixelHeight) * textYScale;
|
const auto lineHeight = static_cast<float>(font->pixelHeight) * textYScale;
|
||||||
|
|
||||||
|
// Draw background box
|
||||||
const auto totalLines = 1u + context.resultCount + (hintEnabled ? 2u : 0u);
|
const auto totalLines = 1u + context.resultCount + (hintEnabled ? 2u : 0u);
|
||||||
const auto arrowPadding = context.resultOffset > 0 || context.hasMoreResults ? FONT_ICON_AUTOCOMPLETE_ARROW_SIZE : 0.0f;
|
const auto arrowPadding = context.resultOffset > 0 || context.hasMoreResults ? FONT_ICON_AUTOCOMPLETE_ARROW_SIZE : 0.0f;
|
||||||
DrawAutocompleteBox(context,
|
DrawAutocompleteBox(context,
|
||||||
@ -335,11 +419,13 @@ namespace Components
|
|||||||
boxWidth + FONT_ICON_AUTOCOMPLETE_BOX_PADDING * 2 + arrowPadding,
|
boxWidth + FONT_ICON_AUTOCOMPLETE_BOX_PADDING * 2 + arrowPadding,
|
||||||
static_cast<float>(totalLines) * lineHeight + FONT_ICON_AUTOCOMPLETE_BOX_PADDING * 2,
|
static_cast<float>(totalLines) * lineHeight + FONT_ICON_AUTOCOMPLETE_BOX_PADDING * 2,
|
||||||
(*con_inputBoxColor)->current.vector);
|
(*con_inputBoxColor)->current.vector);
|
||||||
|
|
||||||
|
// Draw header line "Search results for: xyz"
|
||||||
auto currentY = y + lineHeight;
|
auto currentY = y + lineHeight;
|
||||||
Game::R_AddCmdDrawText(stringSearchStartWith.GetString(), std::numeric_limits<int>::max(), font, x, currentY, textXScale, textYScale, 0.0, TEXT_COLOR, 0);
|
Game::R_AddCmdDrawText(context.stringSearchStartWith.GetString(), std::numeric_limits<int>::max(), font, x, currentY, textXScale, textYScale, 0.0, TEXT_COLOR, 0);
|
||||||
currentY += lineHeight;
|
currentY += lineHeight;
|
||||||
|
|
||||||
|
// 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++)
|
||||||
{
|
{
|
||||||
@ -353,6 +439,7 @@ namespace Components
|
|||||||
currentY += lineHeight;
|
currentY += lineHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
@ -361,12 +448,15 @@ namespace Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextRenderer::DrawAutocomplete(const FontIconAutocompleteContext& context, const float x, const float y, Game::Font_s* font, const float textXScale, const float textYScale)
|
void TextRenderer::DrawAutocomplete(const FontIconAutocompleteInstance instance, const float x, const float y, Game::Font_s* font, const float textXScale, const float textYScale)
|
||||||
{
|
{
|
||||||
|
assert(instance < FONT_ICON_ACI_COUNT);
|
||||||
|
const auto& context = autocompleteContextArray[instance];
|
||||||
|
|
||||||
if (context.inModifiers)
|
if (context.inModifiers)
|
||||||
DrawAutocompleteModifiers(context, x, y, font, textXScale, textYScale);
|
DrawAutocompleteModifiers(instance, x, y, font, textXScale, textYScale);
|
||||||
else
|
else
|
||||||
DrawAutocompleteResults(context, x, y, font, textXScale, textYScale);
|
DrawAutocompleteResults(instance, x, y, font, textXScale, textYScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextRenderer::Con_DrawInput_Hk(const int localClientNum)
|
void TextRenderer::Con_DrawInput_Hk(const int localClientNum)
|
||||||
@ -386,7 +476,7 @@ namespace Components
|
|||||||
{
|
{
|
||||||
const auto x = Game::conDrawInputGlob->leftX;
|
const auto x = Game::conDrawInputGlob->leftX;
|
||||||
const auto y = Game::con_screenMin[1] + 6.0f + static_cast<float>(2 * Game::R_TextHeight(Game::cls->consoleFont));
|
const auto y = Game::con_screenMin[1] + 6.0f + static_cast<float>(2 * Game::R_TextHeight(Game::cls->consoleFont));
|
||||||
DrawAutocomplete(autocompleteContext, x, y, Game::cls->consoleFont, 1.0f, 1.0f);
|
DrawAutocomplete(FONT_ICON_ACI_CONSOLE, x, y, Game::cls->consoleFont, 1.0f, 1.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -415,7 +505,7 @@ namespace Components
|
|||||||
UpdateAutocompleteContext(autocompleteContext, edit, font, ww);
|
UpdateAutocompleteContext(autocompleteContext, edit, font, ww);
|
||||||
if (autocompleteContext.autocompleteActive)
|
if (autocompleteContext.autocompleteActive)
|
||||||
{
|
{
|
||||||
DrawAutocomplete(autocompleteContext, std::floor(xx), std::floor(yy), font, ww, hh);
|
DrawAutocomplete(FONT_ICON_ACI_CHAT, std::floor(xx), std::floor(yy), font, ww, hh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1442,23 +1532,11 @@ namespace Components
|
|||||||
|
|
||||||
void TextRenderer::InitFontIconStrings()
|
void TextRenderer::InitFontIconStrings()
|
||||||
{
|
{
|
||||||
stringSearchStartWith.Load("FONT_ICON_SEARCH_START_WITH");
|
|
||||||
|
|
||||||
stringHintAutoComplete.Load("FONT_ICON_HINT_AUTO_COMPLETE");
|
|
||||||
stringHintAutoComplete.Format("TAB");
|
stringHintAutoComplete.Format("TAB");
|
||||||
|
|
||||||
stringHintModifier.Load("FONT_ICON_HINT_MODIFIER");
|
|
||||||
stringHintModifier.Format(Utils::String::VA("%c", FONT_ICON_MODIFIER_SEPARATOR_CHARACTER));
|
stringHintModifier.Format(Utils::String::VA("%c", FONT_ICON_MODIFIER_SEPARATOR_CHARACTER));
|
||||||
|
stringListHeader.Cache();
|
||||||
stringListHeader.Load("FONT_ICON_MODIFIER_LIST_HEADER");
|
|
||||||
|
|
||||||
stringListFlipHorizontal.Load("FONT_ICON_MODIFIER_LIST_FLIP_HORIZONTAL");
|
|
||||||
stringListFlipHorizontal.Format(Utils::String::VA("%c", FONT_ICON_MODIFIER_FLIP_HORIZONTALLY));
|
stringListFlipHorizontal.Format(Utils::String::VA("%c", FONT_ICON_MODIFIER_FLIP_HORIZONTALLY));
|
||||||
|
|
||||||
stringListFlipVertical.Load("FONT_ICON_MODIFIER_LIST_FLIP_VERTICAL");
|
|
||||||
stringListFlipVertical.Format(Utils::String::VA("%c", FONT_ICON_MODIFIER_FLIP_VERTICALLY));
|
stringListFlipVertical.Format(Utils::String::VA("%c", FONT_ICON_MODIFIER_FLIP_VERTICALLY));
|
||||||
|
|
||||||
stringListBig.Load("FONT_ICON_MODIFIER_LIST_BIG");
|
|
||||||
stringListBig.Format(Utils::String::VA("%c", FONT_ICON_MODIFIER_BIG));
|
stringListBig.Format(Utils::String::VA("%c", FONT_ICON_MODIFIER_BIG));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,108 +42,16 @@ namespace Components
|
|||||||
|
|
||||||
class TextRenderer : public Component
|
class TextRenderer : public Component
|
||||||
{
|
{
|
||||||
public:
|
static constexpr auto STRING_BUFFER_SIZE_BIG = 1024;
|
||||||
enum FontIconAutocompleteInstance : unsigned
|
static constexpr auto STRING_BUFFER_SIZE_SMALL = 128;
|
||||||
{
|
|
||||||
FONT_ICON_ACI_CONSOLE,
|
|
||||||
FONT_ICON_ACI_CHAT,
|
|
||||||
|
|
||||||
FONT_ICON_ACI_COUNT
|
static constexpr auto REFERENCE_SEARCH_START_WITH = "FONT_ICON_SEARCH_START_WITH";
|
||||||
};
|
static constexpr auto REFERENCE_HINT_AUTO_COMPLETE = "FONT_ICON_HINT_AUTO_COMPLETE";
|
||||||
|
static constexpr auto REFERENCE_HINT_MODIFIER = "FONT_ICON_HINT_MODIFIER";
|
||||||
private:
|
static constexpr auto REFERENCE_MODIFIER_LIST_HEADER = "FONT_ICON_MODIFIER_LIST_HEADER";
|
||||||
struct FontIconTableEntry
|
static constexpr auto REFERENCE_MODIFIER_LIST_FLIP_HORIZONTAL = "FONT_ICON_MODIFIER_LIST_FLIP_HORIZONTAL";
|
||||||
{
|
static constexpr auto REFERENCE_MODIFIER_LIST_FLIP_VERTICAL = "FONT_ICON_MODIFIER_LIST_FLIP_VERTICAL";
|
||||||
std::string iconName;
|
static constexpr auto REFERENCE_MODIFIER_LIST_BIG = "FONT_ICON_MODIFIER_LIST_BIG";
|
||||||
std::string materialName;
|
|
||||||
Game::Material* material;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct HsvColor
|
|
||||||
{
|
|
||||||
unsigned char h;
|
|
||||||
unsigned char s;
|
|
||||||
unsigned char v;
|
|
||||||
};
|
|
||||||
|
|
||||||
class FontIconAutocompleteResult
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
std::string fontIconName;
|
|
||||||
std::string materialName;
|
|
||||||
};
|
|
||||||
|
|
||||||
class FontIconAutocompleteContext
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static constexpr auto MAX_RESULTS = 10;
|
|
||||||
|
|
||||||
bool autocompleteActive;
|
|
||||||
bool inModifiers;
|
|
||||||
bool userClosed;
|
|
||||||
unsigned int lastHash;
|
|
||||||
std::string lastQuery;
|
|
||||||
FontIconAutocompleteResult results[MAX_RESULTS];
|
|
||||||
size_t resultCount;
|
|
||||||
bool hasMoreResults;
|
|
||||||
size_t resultOffset;
|
|
||||||
size_t lastResultOffset;
|
|
||||||
size_t selectedOffset;
|
|
||||||
float maxFontIconWidth;
|
|
||||||
float maxMaterialNameWidth;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<size_t S>
|
|
||||||
class FormattedStringBuffer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FormattedStringBuffer()
|
|
||||||
: formattingString(nullptr),
|
|
||||||
stringBuffer{0},
|
|
||||||
stringWidth(-1)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void Load(const char* reference)
|
|
||||||
{
|
|
||||||
formattingString = Game::UI_SafeTranslateString(reference);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* Format(const char* value)
|
|
||||||
{
|
|
||||||
if (formattingString == nullptr)
|
|
||||||
return stringBuffer;
|
|
||||||
|
|
||||||
Game::ConversionArguments conversionArguments{};
|
|
||||||
conversionArguments.args[conversionArguments.argCount++] = value;
|
|
||||||
Game::UI_ReplaceConversions(formattingString, &conversionArguments, stringBuffer, sizeof(stringBuffer));
|
|
||||||
|
|
||||||
stringWidth = -1;
|
|
||||||
return stringBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* GetString() const
|
|
||||||
{
|
|
||||||
if(stringBuffer[0] != '\0')
|
|
||||||
return stringBuffer;
|
|
||||||
if(formattingString)
|
|
||||||
return formattingString;
|
|
||||||
return stringBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
int GetWidth(Game::Font_s* font)
|
|
||||||
{
|
|
||||||
if (stringWidth < 0)
|
|
||||||
stringWidth = Game::R_TextWidth(GetString(), std::numeric_limits<int>::max(), font);
|
|
||||||
|
|
||||||
return stringWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const char* formattingString;
|
|
||||||
char stringBuffer[S];
|
|
||||||
int stringWidth;
|
|
||||||
};
|
|
||||||
|
|
||||||
static constexpr unsigned MY_ALTCOLOR_TWO = 0x0DCE6FFE6;
|
static constexpr unsigned MY_ALTCOLOR_TWO = 0x0DCE6FFE6;
|
||||||
static constexpr unsigned COLOR_MAP_HASH = 0xA0AB1041;
|
static constexpr unsigned COLOR_MAP_HASH = 0xA0AB1041;
|
||||||
@ -180,6 +88,93 @@ namespace Components
|
|||||||
1.0f
|
1.0f
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
static constexpr char FONT_ICON_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_VERTICALLY = 'v';
|
||||||
|
static constexpr char FONT_ICON_MODIFIER_BIG = 'b';
|
||||||
|
|
||||||
|
static constexpr char COLOR_FIRST_CHAR = '0';
|
||||||
|
static constexpr char COLOR_LAST_CHAR = CharForColorIndex(TEXT_COLOR_COUNT - 1);
|
||||||
|
|
||||||
|
enum FontIconAutocompleteInstance : unsigned
|
||||||
|
{
|
||||||
|
FONT_ICON_ACI_CONSOLE,
|
||||||
|
FONT_ICON_ACI_CHAT,
|
||||||
|
|
||||||
|
FONT_ICON_ACI_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FontIconInfo
|
||||||
|
{
|
||||||
|
Game::Material* material;
|
||||||
|
bool flipHorizontal;
|
||||||
|
bool flipVertical;
|
||||||
|
bool big;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct FontIconTableEntry
|
||||||
|
{
|
||||||
|
std::string iconName;
|
||||||
|
std::string materialName;
|
||||||
|
Game::Material* material;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HsvColor
|
||||||
|
{
|
||||||
|
unsigned char h;
|
||||||
|
unsigned char s;
|
||||||
|
unsigned char v;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FontIconAutocompleteResult
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::string fontIconName;
|
||||||
|
std::string materialName;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BufferedLocalizedString
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BufferedLocalizedString(const char* reference, size_t bufferSize);
|
||||||
|
void Cache();
|
||||||
|
const char* Format(const char* value);
|
||||||
|
const char* GetString() const;
|
||||||
|
int GetWidth(FontIconAutocompleteInstance autocompleteInstance, Game::Font_s* font);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char* stringReference;
|
||||||
|
std::unique_ptr<char[]> stringBuffer;
|
||||||
|
size_t stringBufferSize;
|
||||||
|
int stringWidth[FONT_ICON_ACI_COUNT];
|
||||||
|
};
|
||||||
|
|
||||||
|
class FontIconAutocompleteContext
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static constexpr auto MAX_RESULTS = 10;
|
||||||
|
|
||||||
|
bool autocompleteActive;
|
||||||
|
bool inModifiers;
|
||||||
|
bool userClosed;
|
||||||
|
unsigned int lastHash;
|
||||||
|
std::string lastQuery;
|
||||||
|
FontIconAutocompleteResult results[MAX_RESULTS];
|
||||||
|
size_t resultCount;
|
||||||
|
bool hasMoreResults;
|
||||||
|
size_t resultOffset;
|
||||||
|
size_t lastResultOffset;
|
||||||
|
size_t selectedOffset;
|
||||||
|
float maxFontIconWidth;
|
||||||
|
float maxMaterialNameWidth;
|
||||||
|
BufferedLocalizedString stringSearchStartWith;
|
||||||
|
|
||||||
|
FontIconAutocompleteContext();
|
||||||
|
};
|
||||||
|
|
||||||
static unsigned colorTableDefault[TEXT_COLOR_COUNT];
|
static unsigned colorTableDefault[TEXT_COLOR_COUNT];
|
||||||
static unsigned colorTableNew[TEXT_COLOR_COUNT];
|
static unsigned colorTableNew[TEXT_COLOR_COUNT];
|
||||||
static unsigned(*currentColorTable)[TEXT_COLOR_COUNT];
|
static unsigned(*currentColorTable)[TEXT_COLOR_COUNT];
|
||||||
@ -187,16 +182,12 @@ namespace Components
|
|||||||
static std::map<std::string, FontIconTableEntry> fontIconLookup;
|
static std::map<std::string, FontIconTableEntry> fontIconLookup;
|
||||||
static std::vector<FontIconTableEntry> fontIconList;
|
static std::vector<FontIconTableEntry> fontIconList;
|
||||||
|
|
||||||
static constexpr auto STRING_BUFFER_SIZE_BIG = 1024;
|
static BufferedLocalizedString stringHintAutoComplete;
|
||||||
static constexpr auto STRING_BUFFER_SIZE_SMALL = 128;
|
static BufferedLocalizedString stringHintModifier;
|
||||||
static constexpr auto STRING_BUFFER_SIZE_NONE = 1;
|
static BufferedLocalizedString stringListHeader;
|
||||||
static FormattedStringBuffer<STRING_BUFFER_SIZE_BIG> stringSearchStartWith;
|
static BufferedLocalizedString stringListFlipHorizontal;
|
||||||
static FormattedStringBuffer<STRING_BUFFER_SIZE_SMALL> stringHintAutoComplete;
|
static BufferedLocalizedString stringListFlipVertical;
|
||||||
static FormattedStringBuffer<STRING_BUFFER_SIZE_SMALL> stringHintModifier;
|
static BufferedLocalizedString stringListBig;
|
||||||
static FormattedStringBuffer<STRING_BUFFER_SIZE_NONE> stringListHeader;
|
|
||||||
static FormattedStringBuffer<STRING_BUFFER_SIZE_SMALL> stringListFlipHorizontal;
|
|
||||||
static FormattedStringBuffer<STRING_BUFFER_SIZE_SMALL> stringListFlipVertical;
|
|
||||||
static FormattedStringBuffer<STRING_BUFFER_SIZE_SMALL> stringListBig;
|
|
||||||
|
|
||||||
static Dvar::Var cg_newColors;
|
static Dvar::Var cg_newColors;
|
||||||
static Dvar::Var cg_fontIconAutocomplete;
|
static Dvar::Var cg_fontIconAutocomplete;
|
||||||
@ -208,23 +199,6 @@ namespace Components
|
|||||||
static Game::dvar_t** con_inputBoxColor;
|
static Game::dvar_t** con_inputBoxColor;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static constexpr char FONT_ICON_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_VERTICALLY = 'v';
|
|
||||||
static constexpr char FONT_ICON_MODIFIER_BIG = 'b';
|
|
||||||
|
|
||||||
static constexpr char COLOR_FIRST_CHAR = '0';
|
|
||||||
static constexpr char COLOR_LAST_CHAR = CharForColorIndex(TEXT_COLOR_COUNT - 1);
|
|
||||||
|
|
||||||
struct FontIconInfo
|
|
||||||
{
|
|
||||||
Game::Material* material;
|
|
||||||
bool flipHorizontal;
|
|
||||||
bool flipVertical;
|
|
||||||
bool big;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void DrawText2D(const char* text, float x, float y, Game::Font_s* font, float xScale, float yScale, float sinAngle, float cosAngle, Game::GfxColor color, int maxLength, int renderFlags, int cursorPos, char cursorLetter, float padding, Game::GfxColor glowForcedColor, int fxBirthTime, int fxLetterTime, int fxDecayStartTime, int fxDecayDuration, Game::Material* fxMaterial, Game::Material* fxMaterialGlow);
|
static void DrawText2D(const char* text, float x, float y, Game::Font_s* font, float xScale, float yScale, float sinAngle, float cosAngle, Game::GfxColor color, int maxLength, int renderFlags, int cursorPos, char cursorLetter, float padding, Game::GfxColor glowForcedColor, int fxBirthTime, int fxLetterTime, int fxDecayStartTime, int fxDecayDuration, Game::Material* fxMaterial, Game::Material* fxMaterialGlow);
|
||||||
static int R_TextWidth_Hk(const char* text, int maxChars, Game::Font_s* font);
|
static int R_TextWidth_Hk(const char* text, int maxChars, Game::Font_s* font);
|
||||||
static unsigned int ColorIndex(char index);
|
static unsigned int ColorIndex(char index);
|
||||||
@ -247,9 +221,9 @@ namespace Components
|
|||||||
static unsigned HsvToRgb(HsvColor hsv);
|
static unsigned HsvToRgb(HsvColor hsv);
|
||||||
|
|
||||||
static void DrawAutocompleteBox(const FontIconAutocompleteContext& context, float x, float y, float w, float h, const float* color);
|
static void DrawAutocompleteBox(const FontIconAutocompleteContext& context, float x, float y, float w, float h, const float* color);
|
||||||
static void DrawAutocompleteModifiers(const FontIconAutocompleteContext& context, float x, float y, Game::Font_s* font, float textXScale, float textYScale);
|
static void DrawAutocompleteModifiers(FontIconAutocompleteInstance instance, float x, float y, Game::Font_s* font, float textXScale, float textYScale);
|
||||||
static void DrawAutocompleteResults(const FontIconAutocompleteContext& context, float x, float y, Game::Font_s* font, float textXScale, float textYScale);
|
static void DrawAutocompleteResults(FontIconAutocompleteInstance instance, float x, float y, Game::Font_s* font, float textXScale, float textYScale);
|
||||||
static void DrawAutocomplete(const FontIconAutocompleteContext& context, float x, float y, Game::Font_s* font, float textXScale, float textYScale);
|
static void DrawAutocomplete(FontIconAutocompleteInstance instance, float x, float y, Game::Font_s* font, float textXScale, float textYScale);
|
||||||
static void UpdateAutocompleteContextResults(FontIconAutocompleteContext& context, Game::Font_s* font, float textXScale);
|
static void UpdateAutocompleteContextResults(FontIconAutocompleteContext& context, Game::Font_s* font, float textXScale);
|
||||||
static void UpdateAutocompleteContext(FontIconAutocompleteContext& context, const Game::field_t* edit, Game::Font_s* font, const float textXScale);
|
static void UpdateAutocompleteContext(FontIconAutocompleteContext& context, const Game::field_t* edit, Game::Font_s* font, const float textXScale);
|
||||||
static void Field_Draw_Say(int localClientNum, Game::field_t* edit, int x, int y, int horzAlign, int vertAlign);
|
static void Field_Draw_Say(int localClientNum, Game::field_t* edit, int x, int y, int horzAlign, int vertAlign);
|
||||||
|
Loading…
Reference in New Issue
Block a user