fix functionality of non-annotated paragraphs

This commit is contained in:
DeaTh-G 2025-01-19 14:43:40 +01:00
parent 7b97382f49
commit 5b41bb061c
2 changed files with 85 additions and 61 deletions

View file

@ -359,27 +359,18 @@ std::vector<std::string> Split(const char* strStart, const ImFont *font, float f
return result; return result;
} }
ImVec2 MeasureCentredParagraph(const ImFont* font, float fontSize, float lineMargin, std::vector<std::string> lines) Paragraph CalculateAnnotatedParagraph(const std::vector<std::string>& lines)
{ {
struct TextSegment { Paragraph result;
bool annotated;
std::string text;
std::string annotation;
};
auto x = 0.0f; for (const auto& line : lines)
auto y = 0.0f;
for (auto& str : lines)
{ {
///////////////////////////////////////////////////////////////////////
// TODO: Don't duplicate this code segment
std::vector<TextSegment> segments; std::vector<TextSegment> segments;
std::regex regex(R"(\[([^\:]+):([^\]]+)\])"); // Matches "[text:annotation]" std::regex regex(R"(\[([^\:]+):([^\]]+)\])"); // Matches "[text:annotation]"
std::smatch match; std::smatch match;
auto searchStart = str.cbegin(); auto searchStart = line.cbegin();
while (std::regex_search(searchStart, str.cend(), match, regex)) while (std::regex_search(searchStart, line.cend(), match, regex))
{ {
if (searchStart != match[0].first) if (searchStart != match[0].first)
{ {
@ -388,29 +379,75 @@ ImVec2 MeasureCentredParagraph(const ImFont* font, float fontSize, float lineMar
segments.push_back({ true, match[1].str(), match[2].str() }); segments.push_back({ true, match[1].str(), match[2].str() });
result.annotated = true;
searchStart = match[0].second; searchStart = match[0].second;
} }
if (searchStart != str.cend()) if (searchStart != line.cend())
{ {
segments.push_back({ false, std::string(searchStart, str.cend()), "" }); segments.push_back({ false, std::string(searchStart, line.cend()), "" });
} }
result.lines.push_back(segments);
}
return result;
}
std::vector<std::string> RemoveAnnotationFromParagraph(const std::vector<std::string>& lines)
{
std::vector<std::string> result;
const auto& annotatedLines = CalculateAnnotatedParagraph(lines).lines;
for (auto& annotatedLine : annotatedLines)
{
std::string annotationRemovedLine = ""; std::string annotationRemovedLine = "";
for (const auto& segment : segments) for (const auto& segment : annotatedLine)
{ {
annotationRemovedLine += segment.text; annotationRemovedLine += segment.text;
} }
///////////////////////////////////////////////////////////////////////
auto textSize = font->CalcTextSizeA(fontSize, FLT_MAX, 0, annotationRemovedLine.c_str()); result.push_back(annotationRemovedLine);
auto annotationSize = font->CalcTextSizeA(fontSize * 0.6f, FLT_MAX, 0, ""); }
return result;
}
std::string RemoveAnnotationFromParagraphLine(const std::vector<TextSegment>& annotatedLine)
{
std::string result = "";
for (auto& segment : annotatedLine)
{
result += segment.text;
}
return result;
}
ImVec2 MeasureCentredParagraph(const ImFont* font, float fontSize, float lineMargin, std::vector<std::string> lines)
{
auto x = 0.0f;
auto y = 0.0f;
const auto& annotatedLines = CalculateAnnotatedParagraph(lines);
std::vector<std::string> annotationRemovedLines;
for (const auto& line : annotatedLines.lines)
{
annotationRemovedLines.emplace_back(RemoveAnnotationFromParagraphLine(line));
}
for (auto& line : annotationRemovedLines)
{
auto textSize = font->CalcTextSizeA(fontSize, FLT_MAX, 0, line.c_str());
auto annotationSize = font->CalcTextSizeA(fontSize * 0.55f, FLT_MAX, 0, "");
x = std::max(x, textSize.x); x = std::max(x, textSize.x);
y += textSize.y + Scale(lineMargin); y += textSize.y + Scale(lineMargin);
// TODO: This will case the text to account for annotation even if there's none included ever. This should not be the case. if (annotatedLines.annotated && &line != &lines.back() && &line != &lines.front())
if (&str != &lines.back())
{ {
y += annotationSize.y; y += annotationSize.y;
} }
@ -430,41 +467,11 @@ void DrawCentredParagraph(const ImFont* font, float fontSize, float maxWidth, co
auto paragraphSize = MeasureCentredParagraph(font, fontSize, lineMargin, lines); auto paragraphSize = MeasureCentredParagraph(font, fontSize, lineMargin, lines);
auto offsetY = 0.0f; auto offsetY = 0.0f;
struct TextSegment { const auto& annotatedLines = CalculateAnnotatedParagraph(lines);
bool annotated;
std::string text;
std::string annotation;
};
for (const auto& line : lines) for (const auto& annotatedLine : annotatedLines.lines)
{ {
std::vector<TextSegment> segments; const auto& annotationRemovedLine = RemoveAnnotationFromParagraphLine(annotatedLine);
std::regex regex(R"(\[([^\:]+):([^\]]+)\])"); // Matches "[text:annotation]"
std::smatch match;
auto searchStart = line.cbegin();
while (std::regex_search(searchStart, line.cend(), match, regex))
{
if (searchStart != match[0].first)
{
segments.push_back({ false, std::string(searchStart, match[0].first), ""});
}
segments.push_back({ true, match[1].str(), match[2].str() });
searchStart = match[0].second;
}
if (searchStart != line.cend())
{
segments.push_back({ false, std::string(searchStart, line.cend()), "" });
}
std::string annotationRemovedLine = "";
for (const auto& segment : segments)
{
annotationRemovedLine += segment.text;
}
auto textSize = font->CalcTextSizeA(fontSize, FLT_MAX, 0, annotationRemovedLine.c_str()); auto textSize = font->CalcTextSizeA(fontSize, FLT_MAX, 0, annotationRemovedLine.c_str());
auto annotationSize = font->CalcTextSizeA(fontSize, FLT_MAX, 0, ""); auto annotationSize = font->CalcTextSizeA(fontSize, FLT_MAX, 0, "");
@ -473,7 +480,7 @@ void DrawCentredParagraph(const ImFont* font, float fontSize, float maxWidth, co
? centre.x - paragraphSize.x / 2 ? centre.x - paragraphSize.x / 2
: centre.x - textSize.x / 2; : centre.x - textSize.x / 2;
for (const auto& segment : segments) for (const auto& segment : annotatedLine)
{ {
textSize = font->CalcTextSizeA(fontSize, FLT_MAX, 0, segment.text.c_str()); textSize = font->CalcTextSizeA(fontSize, FLT_MAX, 0, segment.text.c_str());
@ -481,19 +488,22 @@ void DrawCentredParagraph(const ImFont* font, float fontSize, float maxWidth, co
if (segment.annotated) if (segment.annotated)
{ {
annotationSize = font->CalcTextSizeA(fontSize * 0.6f, FLT_MAX, 0, segment.annotation.c_str()); annotationSize = font->CalcTextSizeA(fontSize * 0.55f, FLT_MAX, 0, segment.annotation.c_str());
float annotationX = textX + (textSize.x - annotationSize.x) / 2.0f; float annotationX = textX + (textSize.x - annotationSize.x) / 2.0f;
annotationDrawMethod(segment.annotation.c_str(), fontSize * 0.6f, { annotationX, textY - (fontSize * 0.6f) }); annotationDrawMethod(segment.annotation.c_str(), fontSize * 0.55f, { annotationX, textY - (fontSize * 0.55f) });
} }
drawMethod(segment.text.c_str(), { textX, textY }); drawMethod(segment.text.c_str(), { textX, textY });
textX += textSize.x; textX += textSize.x;
} }
// TODO: This will case the text to account for annotation even if there's none included ever. This should not be the case. offsetY += textSize.y + Scale(lineMargin);
offsetY += textSize.y + annotationSize.y + Scale(lineMargin); if (annotatedLines.annotated)
{
offsetY += annotationSize.y;
}
} }
} }

View file

@ -19,6 +19,17 @@ extern std::unique_ptr<GuestTexture> g_texLight;
extern std::unique_ptr<GuestTexture> g_texSelectFade; extern std::unique_ptr<GuestTexture> g_texSelectFade;
extern std::unique_ptr<GuestTexture> g_texSelectFill; extern std::unique_ptr<GuestTexture> g_texSelectFill;
struct TextSegment {
bool annotated;
std::string text;
std::string annotation;
};
struct Paragraph {
bool annotated;
std::vector<std::vector<TextSegment>> lines;
};
void InitImGuiUtils(); void InitImGuiUtils();
void SetGradient(const ImVec2& min, const ImVec2& max, ImU32 top, ImU32 bottom); void SetGradient(const ImVec2& min, const ImVec2& max, ImU32 top, ImU32 bottom);
@ -47,6 +58,9 @@ void DrawTextWithShadow(const ImFont* font, float fontSize, const ImVec2& pos, I
float CalcWidestTextSize(const ImFont* font, float fontSize, std::span<std::string> strs); float CalcWidestTextSize(const ImFont* font, float fontSize, std::span<std::string> strs);
std::string Truncate(const std::string& input, size_t maxLength, bool useEllipsis = true, bool usePrefixEllipsis = false); std::string Truncate(const std::string& input, size_t maxLength, bool useEllipsis = true, bool usePrefixEllipsis = false);
std::vector<std::string> Split(const char* strStart, const ImFont* font, float fontSize, float maxWidth); std::vector<std::string> Split(const char* strStart, const ImFont* font, float fontSize, float maxWidth);
Paragraph CalculateAnnotatedParagraph(const std::vector<std::string>& lines);
std::vector<std::string> RemoveAnnotationFromParagraph(const std::vector<std::string>& lines);
std::string RemoveAnnotationFromParagraphLine(const std::vector<TextSegment>& annotatedLine);
ImVec2 MeasureCentredParagraph(const ImFont* font, float fontSize, float lineMargin, std::vector<std::string> lines); ImVec2 MeasureCentredParagraph(const ImFont* font, float fontSize, float lineMargin, std::vector<std::string> lines);
ImVec2 MeasureCentredParagraph(const ImFont* font, float fontSize, float maxWidth, float lineMargin, const char* text); ImVec2 MeasureCentredParagraph(const ImFont* font, float fontSize, float maxWidth, float lineMargin, const char* text);
void DrawCentredParagraph(const ImFont* font, float fontSize, float maxWidth, const ImVec2& centre, float lineMargin, const char* text, std::function<void(const char*, ImVec2)> drawMethod); void DrawCentredParagraph(const ImFont* font, float fontSize, float maxWidth, const ImVec2& centre, float lineMargin, const char* text, std::function<void(const char*, ImVec2)> drawMethod);