mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2025-04-28 13:27:58 +03:00
Add ruby annotation support for text displayed in various spaces. (#232)
* allow preliminary annotation on DrawCenteredParagraph * improve annotated text line spacing * fix functionality of non-annotated paragraphs * a lot of very bad code that but line wrapping works * support ruby annotations for options menu descriptions * make installer wizard more accurate * remove wrapper function * add furigana support to config names * add furigana support for marquee text for options * fully support annotated text in options menu * fix option names being split to multiple lines * fix and cleanup installer wizard text placements * implement furigana support for message window * remove regex usage * remove excessive const ref usage
This commit is contained in:
parent
091b4ef089
commit
4816d4aa9d
5 changed files with 465 additions and 74 deletions
|
@ -189,7 +189,68 @@ void DrawPauseHeaderContainer(ImVec2 min, ImVec2 max, float alpha)
|
|||
drawList->AddImage(g_texGeneralWindow.get(), { max.x - commonWidth, min.y }, max, GET_UV_COORDS(right), colour);
|
||||
}
|
||||
|
||||
void DrawTextWithMarquee(const ImFont* font, float fontSize, const ImVec2& pos, const ImVec2& min, const ImVec2& max, ImU32 color, const char* text, double time, double delay, double speed)
|
||||
void DrawTextBasic(const ImFont* font, float fontSize, const ImVec2& pos, ImU32 colour, const char* text)
|
||||
{
|
||||
auto drawList = ImGui::GetForegroundDrawList();
|
||||
|
||||
drawList->AddText(font, fontSize, pos, colour, text, nullptr);
|
||||
}
|
||||
|
||||
void DrawTextWithMarquee(const ImFont* font, float fontSize, const ImVec2& position, const ImVec2& min, const ImVec2& max, ImU32 color, const char* text, double time, double delay, double speed)
|
||||
{
|
||||
auto drawList = ImGui::GetForegroundDrawList();
|
||||
auto rectWidth = max.x - min.x;
|
||||
auto textSize = font->CalcTextSizeA(fontSize, FLT_MAX, 0, text);
|
||||
auto textX = position.x - fmodf(std::max(0.0, ImGui::GetTime() - (time + delay)) * speed, textSize.x + rectWidth);
|
||||
|
||||
drawList->PushClipRect(min, max, true);
|
||||
|
||||
if (textX <= position.x)
|
||||
{
|
||||
DrawRubyAnnotatedText
|
||||
(
|
||||
font,
|
||||
fontSize,
|
||||
FLT_MAX,
|
||||
{ textX, position.y },
|
||||
0.0f,
|
||||
text,
|
||||
[=](const char* str, ImVec2 pos)
|
||||
{
|
||||
DrawTextBasic(font, fontSize, pos, color, str);
|
||||
},
|
||||
[=](const char* str, float size, ImVec2 pos)
|
||||
{
|
||||
DrawTextBasic(font, size, pos, color, str);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (textX + textSize.x < position.x)
|
||||
{
|
||||
DrawRubyAnnotatedText
|
||||
(
|
||||
font,
|
||||
fontSize,
|
||||
FLT_MAX,
|
||||
{ textX + textSize.x + rectWidth, position.y },
|
||||
0.0f,
|
||||
text,
|
||||
[=](const char* str, ImVec2 pos)
|
||||
{
|
||||
DrawTextBasic(font, fontSize, pos, color, str);
|
||||
},
|
||||
[=](const char* str, float size, ImVec2 pos)
|
||||
{
|
||||
DrawTextBasic(font, size, pos, color, str);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
drawList->PopClipRect();
|
||||
}
|
||||
|
||||
void DrawTextWithMarqueeShadow(const ImFont* font, float fontSize, const ImVec2& pos, const ImVec2& min, const ImVec2& max, ImU32 colour, const char* text, double time, double delay, double speed, float offset, float radius, ImU32 shadowColour)
|
||||
{
|
||||
auto drawList = ImGui::GetForegroundDrawList();
|
||||
auto rectWidth = max.x - min.x;
|
||||
|
@ -199,10 +260,10 @@ void DrawTextWithMarquee(const ImFont* font, float fontSize, const ImVec2& pos,
|
|||
drawList->PushClipRect(min, max, true);
|
||||
|
||||
if (textX <= pos.x)
|
||||
drawList->AddText(font, fontSize, { textX, pos.y }, color, text);
|
||||
DrawTextWithShadow(font, fontSize, { textX, pos.y }, colour, text, offset, radius, shadowColour);
|
||||
|
||||
if (textX + textSize.x < pos.x)
|
||||
drawList->AddText(font, fontSize, { textX + textSize.x + rectWidth, pos.y }, color, text);
|
||||
DrawTextWithShadow(font, fontSize, { textX + textSize.x + rectWidth, pos.y }, colour, text, offset, radius, shadowColour);
|
||||
|
||||
drawList->PopClipRect();
|
||||
}
|
||||
|
@ -273,6 +334,84 @@ std::string Truncate(const std::string& input, size_t maxLength, bool useEllipsi
|
|||
return input;
|
||||
}
|
||||
|
||||
std::pair<std::string, std::map<std::string, std::string>> RemoveRubyAnnotations(const char* input) {
|
||||
std::string output;
|
||||
std::map<std::string, std::string> rubyMap;
|
||||
std::string currentMain, currentRuby;
|
||||
size_t idx = 0;
|
||||
|
||||
while (input[idx] != '\0')
|
||||
{
|
||||
if (input[idx] == '[')
|
||||
{
|
||||
idx++;
|
||||
currentMain.clear();
|
||||
currentRuby.clear();
|
||||
|
||||
while (input[idx] != ':' && input[idx] != ']' && input[idx] != '\0')
|
||||
{
|
||||
currentMain += input[idx++];
|
||||
}
|
||||
if (input[idx] == ':')
|
||||
{
|
||||
idx++;
|
||||
while (input[idx] != ']' && input[idx] != '\0')
|
||||
{
|
||||
currentRuby += input[idx++];
|
||||
}
|
||||
}
|
||||
if (input[idx] == ']')
|
||||
{
|
||||
idx++;
|
||||
}
|
||||
|
||||
if (!currentMain.empty() && !currentRuby.empty())
|
||||
{
|
||||
rubyMap[currentMain] = currentRuby;
|
||||
}
|
||||
|
||||
output += currentMain;
|
||||
}
|
||||
else
|
||||
{
|
||||
output += input[idx++];
|
||||
}
|
||||
}
|
||||
|
||||
return { output, rubyMap };
|
||||
}
|
||||
|
||||
std::string ReAddRubyAnnotations(const std::string_view& wrappedText, const std::map<std::string, std::string>& rubyMap) {
|
||||
std::string annotatedText;
|
||||
size_t idx = 0;
|
||||
size_t length = wrappedText.length();
|
||||
|
||||
while (idx < length) {
|
||||
bool matched = false;
|
||||
for (const auto& [mainText, rubyText] : rubyMap)
|
||||
{
|
||||
if (wrappedText.substr(idx, mainText.length()) == mainText)
|
||||
{
|
||||
annotatedText += "[";
|
||||
annotatedText += mainText;
|
||||
annotatedText += ":";
|
||||
annotatedText += rubyText;
|
||||
annotatedText += "]";
|
||||
|
||||
idx += mainText.length();
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!matched)
|
||||
{
|
||||
annotatedText += wrappedText[idx++];
|
||||
}
|
||||
}
|
||||
|
||||
return annotatedText;
|
||||
}
|
||||
|
||||
std::vector<std::string> Split(const char* strStart, const ImFont *font, float fontSize, float maxWidth)
|
||||
{
|
||||
if (!strStart)
|
||||
|
@ -359,17 +498,111 @@ std::vector<std::string> Split(const char* strStart, const ImFont *font, float f
|
|||
return result;
|
||||
}
|
||||
|
||||
ImVec2 MeasureCentredParagraph(const ImFont* font, float fontSize, float lineMargin, std::vector<std::string> lines)
|
||||
Paragraph CalculateAnnotatedParagraph(const std::vector<std::string>& lines)
|
||||
{
|
||||
Paragraph result;
|
||||
|
||||
for (const auto& line : lines)
|
||||
{
|
||||
std::vector<TextSegment> segments;
|
||||
|
||||
size_t pos = 0;
|
||||
size_t start = 0;
|
||||
|
||||
while ((start = line.find('[', pos)) != std::string::npos)
|
||||
{
|
||||
size_t end = line.find(']', start);
|
||||
if (end == std::string::npos)
|
||||
break;
|
||||
|
||||
size_t colon = line.find(':', start);
|
||||
if (colon != std::string::npos && colon < end)
|
||||
{
|
||||
if (start != pos)
|
||||
{
|
||||
segments.push_back({ false, line.substr(pos, start - pos), "" });
|
||||
}
|
||||
|
||||
segments.push_back({ true, line.substr(start + 1, colon - start - 1), line.substr(colon + 1, end - colon - 1) });
|
||||
|
||||
result.annotated = true;
|
||||
pos = end + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos = start + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (pos < line.size())
|
||||
{
|
||||
segments.push_back({ false, line.substr(pos), "" });
|
||||
}
|
||||
|
||||
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 paragraph = CalculateAnnotatedParagraph(lines);
|
||||
|
||||
for (auto& annotatedLine : paragraph.lines)
|
||||
{
|
||||
std::string annotationRemovedLine = "";
|
||||
for (const auto& segment : annotatedLine)
|
||||
{
|
||||
annotationRemovedLine += segment.text;
|
||||
}
|
||||
|
||||
result.push_back(annotationRemovedLine);
|
||||
}
|
||||
|
||||
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, const std::vector<std::string>& lines)
|
||||
{
|
||||
auto x = 0.0f;
|
||||
auto y = 0.0f;
|
||||
|
||||
for (auto& str : lines)
|
||||
const auto paragraph = CalculateAnnotatedParagraph(lines);
|
||||
|
||||
std::vector<std::string> annotationRemovedLines;
|
||||
for (const auto& line : paragraph.lines)
|
||||
{
|
||||
auto textSize = font->CalcTextSizeA(fontSize, FLT_MAX, 0, str.c_str());
|
||||
annotationRemovedLines.emplace_back(RemoveAnnotationFromParagraphLine(line));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < annotationRemovedLines.size(); i++)
|
||||
{
|
||||
auto& line = annotationRemovedLines[i];
|
||||
|
||||
auto textSize = font->CalcTextSizeA(fontSize, FLT_MAX, 0, line.c_str());
|
||||
auto annotationSize = font->CalcTextSizeA(fontSize * ANNOTATION_FONT_SIZE_MODIFIER, FLT_MAX, 0, "");
|
||||
|
||||
x = std::max(x, textSize.x);
|
||||
y += textSize.y + Scale(lineMargin);
|
||||
|
||||
if (paragraph.annotated)
|
||||
{
|
||||
y += annotationSize.y;
|
||||
}
|
||||
}
|
||||
|
||||
return { x, y };
|
||||
|
@ -380,47 +613,66 @@ ImVec2 MeasureCentredParagraph(const ImFont* font, float fontSize, float maxWidt
|
|||
return MeasureCentredParagraph(font, fontSize, lineMargin, Split(text, font, fontSize, maxWidth));
|
||||
}
|
||||
|
||||
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 DrawRubyAnnotatedText(const ImFont* font, float fontSize, float maxWidth, const ImVec2& pos, float lineMargin, const char* text, std::function<void(const char*, ImVec2)> drawMethod, std::function<void(const char*, float, ImVec2)> annotationDrawMethod, bool isCentred)
|
||||
{
|
||||
auto lines = Split(text, font, fontSize, maxWidth);
|
||||
auto paragraphSize = MeasureCentredParagraph(font, fontSize, lineMargin, lines);
|
||||
auto offsetY = 0.0f;
|
||||
float annotationFontSize = fontSize * ANNOTATION_FONT_SIZE_MODIFIER;
|
||||
|
||||
for (int i = 0; i < lines.size(); i++)
|
||||
const auto input = RemoveRubyAnnotations(text);
|
||||
auto lines = Split(input.first.c_str(), font, fontSize, maxWidth);
|
||||
|
||||
for (auto& line : lines)
|
||||
{
|
||||
auto& str = lines[i];
|
||||
auto textSize = font->CalcTextSizeA(fontSize, FLT_MAX, 0, str.c_str());
|
||||
line = ReAddRubyAnnotations(line, input.second);
|
||||
}
|
||||
|
||||
auto paragraphSize = MeasureCentredParagraph(font, fontSize, lineMargin, lines);
|
||||
float offsetY = 0.0f;
|
||||
|
||||
auto textX = str.starts_with("- ")
|
||||
? centre.x - paragraphSize.x / 2
|
||||
: centre.x - textSize.x / 2;
|
||||
const auto paragraph = CalculateAnnotatedParagraph(lines);
|
||||
|
||||
auto textY = centre.y - paragraphSize.y / 2 + offsetY;
|
||||
for (const auto& annotatedLine : paragraph.lines)
|
||||
{
|
||||
const auto annotationRemovedLine = RemoveAnnotationFromParagraphLine(annotatedLine);
|
||||
|
||||
drawMethod(str.c_str(), { textX, textY });
|
||||
auto textSize = font->CalcTextSizeA(fontSize, FLT_MAX, 0, annotationRemovedLine.c_str());
|
||||
auto annotationSize = font->CalcTextSizeA(annotationFontSize, FLT_MAX, 0, "");
|
||||
|
||||
float textX = pos.x;
|
||||
float textY = pos.y + offsetY;
|
||||
|
||||
if (isCentred)
|
||||
{
|
||||
textX = annotationRemovedLine.starts_with("- ")
|
||||
? pos.x - paragraphSize.x / 2
|
||||
: pos.x - textSize.x / 2;
|
||||
|
||||
textY = pos.y - paragraphSize.y / 2 + offsetY;
|
||||
}
|
||||
|
||||
for (const auto& segment : annotatedLine)
|
||||
{
|
||||
textSize = font->CalcTextSizeA(fontSize, FLT_MAX, 0, segment.text.c_str());
|
||||
|
||||
if (segment.annotated)
|
||||
{
|
||||
annotationSize = font->CalcTextSizeA(annotationFontSize, FLT_MAX, 0, segment.annotation.c_str());
|
||||
float annotationX = textX + (textSize.x - annotationSize.x) / 2.0f;
|
||||
|
||||
annotationDrawMethod(segment.annotation.c_str(), annotationFontSize, { annotationX, textY - annotationFontSize });
|
||||
}
|
||||
|
||||
drawMethod(segment.text.c_str(), { textX, textY });
|
||||
textX += textSize.x;
|
||||
}
|
||||
|
||||
offsetY += textSize.y + Scale(lineMargin);
|
||||
if (paragraph.annotated)
|
||||
{
|
||||
offsetY += annotationSize.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrawTextWithMarqueeShadow(const ImFont* font, float fontSize, const ImVec2& pos, const ImVec2& min, const ImVec2& max, ImU32 colour, const char* text, double time, double delay, double speed, float offset, float radius, ImU32 shadowColour)
|
||||
{
|
||||
auto drawList = ImGui::GetForegroundDrawList();
|
||||
auto rectWidth = max.x - min.x;
|
||||
auto textSize = font->CalcTextSizeA(fontSize, FLT_MAX, 0, text);
|
||||
auto textX = pos.x - fmodf(std::max(0.0, ImGui::GetTime() - (time + delay)) * speed, textSize.x + rectWidth);
|
||||
|
||||
drawList->PushClipRect(min, max, true);
|
||||
|
||||
if (textX <= pos.x)
|
||||
DrawTextWithShadow(font, fontSize, { textX, pos.y }, colour, text, offset, radius, shadowColour);
|
||||
|
||||
if (textX + textSize.x < pos.x)
|
||||
DrawTextWithShadow(font, fontSize, { textX + textSize.x + rectWidth, pos.y }, colour, text, offset, radius, shadowColour);
|
||||
|
||||
drawList->PopClipRect();
|
||||
}
|
||||
|
||||
float Lerp(float a, float b, float t)
|
||||
{
|
||||
return a + (b - a) * t;
|
||||
|
|
|
@ -14,11 +14,24 @@
|
|||
|
||||
#define BREATHE_MOTION(start, end, time, rate) Lerp(start, end, (sin((ImGui::GetTime() - time) * (2.0f * M_PI / rate)) + 1.0f) / 2.0f)
|
||||
|
||||
constexpr float ANNOTATION_FONT_SIZE_MODIFIER = 0.6f;
|
||||
|
||||
extern std::unique_ptr<GuestTexture> g_texGeneralWindow;
|
||||
extern std::unique_ptr<GuestTexture> g_texLight;
|
||||
extern std::unique_ptr<GuestTexture> g_texSelectFade;
|
||||
extern std::unique_ptr<GuestTexture> g_texSelectFill;
|
||||
|
||||
struct TextSegment {
|
||||
bool annotated;
|
||||
std::string text;
|
||||
std::string annotation;
|
||||
};
|
||||
|
||||
struct Paragraph {
|
||||
bool annotated = false;
|
||||
std::vector<std::vector<TextSegment>> lines;
|
||||
};
|
||||
|
||||
void InitImGuiUtils();
|
||||
|
||||
void SetGradient(const ImVec2& min, const ImVec2& max, ImU32 top, ImU32 bottom);
|
||||
|
@ -40,17 +53,23 @@ float Scale(float size);
|
|||
double ComputeLinearMotion(double duration, double offset, double total);
|
||||
double ComputeMotion(double duration, double offset, double total);
|
||||
void DrawPauseContainer(ImVec2 min, ImVec2 max, float alpha = 1);
|
||||
void DrawTextBasic(const ImFont* font, float fontSize, const ImVec2& pos, ImU32 colour, const char* text);
|
||||
void DrawPauseHeaderContainer(ImVec2 min, ImVec2 max, float alpha = 1);
|
||||
void DrawTextWithMarquee(const ImFont* font, float fontSize, const ImVec2& pos, const ImVec2& min, const ImVec2& max, ImU32 color, const char* text, double time, double delay, double speed);
|
||||
void DrawTextWithMarquee(const ImFont* font, float fontSize, const ImVec2& position, const ImVec2& min, const ImVec2& max, ImU32 color, const char* text, double time, double delay, double speed);
|
||||
void DrawTextWithMarqueeShadow(const ImFont* font, float fontSize, const ImVec2& pos, const ImVec2& min, const ImVec2& max, ImU32 colour, const char* text, double time, double delay, double speed, float offset = 2.0f, float radius = 1.0f, ImU32 shadowColour = IM_COL32(0, 0, 0, 255));
|
||||
void DrawTextWithOutline(const ImFont* font, float fontSize, const ImVec2& pos, ImU32 color, const char* text, float outlineSize, ImU32 outlineColor, uint32_t shaderModifier = IMGUI_SHADER_MODIFIER_NONE);
|
||||
void DrawTextWithShadow(const ImFont* font, float fontSize, const ImVec2& pos, ImU32 colour, const char* text, float offset = 2.0f, float radius = 1.0f, ImU32 shadowColour = IM_COL32(0, 0, 0, 255));
|
||||
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::pair<std::string, std::map<std::string, std::string>> RemoveRubyAnnotations(const char* input);
|
||||
std::string ReAddRubyAnnotations(const std::string_view& wrappedText, const std::map<std::string, std::string>& rubyMap);
|
||||
std::vector<std::string> Split(const char* strStart, const ImFont* font, float fontSize, float maxWidth);
|
||||
ImVec2 MeasureCentredParagraph(const ImFont* font, float fontSize, float lineMargin, std::vector<std::string> lines);
|
||||
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, const std::vector<std::string>& lines);
|
||||
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 DrawTextWithMarqueeShadow(const ImFont* font, float fontSize, const ImVec2& pos, const ImVec2& min, const ImVec2& max, ImU32 colour, const char* text, double time, double delay, double speed, float offset = 2.0f, float radius = 1.0f, ImU32 shadowColour = IM_COL32(0, 0, 0, 255));
|
||||
void DrawRubyAnnotatedText(const ImFont* font, float fontSize, float maxWidth, const ImVec2& pos, float lineMargin, const char* text, std::function<void(const char*, ImVec2)> drawMethod, std::function<void(const char*, float, ImVec2)> annotationDrawMethod, bool isCentred = false);
|
||||
float Lerp(float a, float b, float t);
|
||||
float Cubic(float a, float b, float t);
|
||||
float Hermite(float a, float b, float t);
|
||||
|
|
|
@ -65,19 +65,19 @@ static constexpr double PULSE_ANIMATION_LOOP_SPEED = 1.5;
|
|||
static constexpr double PULSE_ANIMATION_LOOP_DELAY = 0.5;
|
||||
static constexpr double PULSE_ANIMATION_LOOP_FADE_HIGH_POINT = 0.5;
|
||||
|
||||
constexpr float IMAGE_X = 165.0f;
|
||||
constexpr float IMAGE_Y = 106.0f;
|
||||
constexpr float IMAGE_X = 161.5f;
|
||||
constexpr float IMAGE_Y = 103.5f;
|
||||
constexpr float IMAGE_WIDTH = 512.0f;
|
||||
constexpr float IMAGE_HEIGHT = 512.0f;
|
||||
|
||||
constexpr float CONTAINER_X = 510.0f;
|
||||
constexpr float CONTAINER_Y = 225.0f;
|
||||
constexpr float CONTAINER_WIDTH = 528.0f;
|
||||
constexpr float CONTAINER_HEIGHT = 245.0f;
|
||||
constexpr float CONTAINER_X = 513.0f;
|
||||
constexpr float CONTAINER_Y = 226.0f;
|
||||
constexpr float CONTAINER_WIDTH = 526.5f;
|
||||
constexpr float CONTAINER_HEIGHT = 246.0f;
|
||||
constexpr float SIDE_CONTAINER_WIDTH = CONTAINER_WIDTH / 2.0f;
|
||||
|
||||
constexpr float BOTTOM_X_GAP = 4.0f;
|
||||
constexpr float BOTTOM_Y_GAP = 4.0f;
|
||||
constexpr float BOTTOM_Y_GAP = 6.0f;
|
||||
constexpr float CONTAINER_BUTTON_WIDTH = 250.0f;
|
||||
constexpr float CONTAINER_BUTTON_GAP = 9.0f;
|
||||
constexpr float BUTTON_HEIGHT = 22.0f;
|
||||
|
@ -512,9 +512,9 @@ static void DrawHeaderIcons()
|
|||
{
|
||||
auto drawList = ImGui::GetForegroundDrawList();
|
||||
|
||||
float iconsPosX = 253.0f;
|
||||
float iconsPosY = 79.0f;
|
||||
float iconsScale = 58;
|
||||
float iconsPosX = 256.0f;
|
||||
float iconsPosY = 80.0f;
|
||||
float iconsScale = 62.0f;
|
||||
|
||||
// Miles Electric Icon
|
||||
float milesIconMotion = ComputeMotionInstaller(g_appearTime, g_disappearTime, MILES_ICON_ANIMATION_TIME, MILES_ICON_ANIMATION_DURATION);
|
||||
|
@ -594,8 +594,8 @@ static void DrawScanlineBars()
|
|||
DrawTextWithOutline
|
||||
(
|
||||
g_dfsogeistdFont,
|
||||
Scale(42),
|
||||
{ g_aspectRatioOffsetX + Scale(285), Scale(57) },
|
||||
Scale(48.0f),
|
||||
{ g_aspectRatioOffsetX + Scale(288.0f), Scale(54.5f) },
|
||||
IM_COL32(255, 195, 0, 255 * alphaMotion * breatheMotion),
|
||||
headerText.c_str(), 4,
|
||||
IM_COL32(0, 0, 0, 255 * alphaMotion * breatheMotion),
|
||||
|
@ -669,17 +669,18 @@ static void DrawContainer(ImVec2 min, ImVec2 max, bool isTextArea)
|
|||
}
|
||||
|
||||
// The draw area
|
||||
drawList->PushClipRect({ min.x + gridSize * 2.0f, min.y + gridSize * 2.0f }, { max.x - gridSize * 2.0f + 1.0f, max.y - gridSize * 2.0f + 1.0f });
|
||||
drawList->PushClipRect({ min.x - gridSize * 2.0f, min.y + gridSize * 2.0f }, { max.x - gridSize * 2.0f + 1.0f, max.y - gridSize * 2.0f + 1.0f });
|
||||
}
|
||||
|
||||
static void DrawDescriptionContainer()
|
||||
{
|
||||
auto &res = ImGui::GetIO().DisplaySize;
|
||||
auto drawList = ImGui::GetForegroundDrawList();
|
||||
auto fontSize = Scale(26.0f);
|
||||
auto fontSize = Scale(28.0f);
|
||||
auto annotationFontSize = fontSize * ANNOTATION_FONT_SIZE_MODIFIER;
|
||||
|
||||
ImVec2 descriptionMin = { round(g_aspectRatioOffsetX + Scale(CONTAINER_X)), round(g_aspectRatioOffsetY + Scale(CONTAINER_Y)) };
|
||||
ImVec2 descriptionMax = { round(g_aspectRatioOffsetX + Scale(CONTAINER_X + CONTAINER_WIDTH)), round(g_aspectRatioOffsetY + Scale(CONTAINER_Y + CONTAINER_HEIGHT)) };
|
||||
ImVec2 descriptionMin = { round(g_aspectRatioOffsetX + Scale(CONTAINER_X + 0.5f)), round(g_aspectRatioOffsetY + Scale(CONTAINER_Y + 0.5f)) };
|
||||
ImVec2 descriptionMax = { round(g_aspectRatioOffsetX + Scale(CONTAINER_X + 0.5f + CONTAINER_WIDTH)), round(g_aspectRatioOffsetY + Scale(CONTAINER_Y + 0.5f + CONTAINER_HEIGHT)) };
|
||||
SetProceduralOrigin(descriptionMin);
|
||||
DrawContainer(descriptionMin, descriptionMax, true);
|
||||
|
||||
|
@ -706,19 +707,53 @@ static void DrawDescriptionContainer()
|
|||
auto clipRectMin = drawList->GetClipRectMin();
|
||||
auto clipRectMax = drawList->GetClipRectMax();
|
||||
|
||||
drawList->AddText
|
||||
float textX = clipRectMin.x + fontSize;
|
||||
float textY = clipRectMin.y - Scale(1.0f);
|
||||
|
||||
float lineMargin = 5.0f;
|
||||
|
||||
if (Config::Language == ELanguage::Japanese)
|
||||
{
|
||||
lineMargin = 5.5f;
|
||||
|
||||
// Removing some padding of the applied due to the inclusion of annotation for Japanese
|
||||
textX -= (fontSize + Scale(1.5f));
|
||||
textY -= Scale(7.0f);
|
||||
|
||||
// The annotation (and thus the Japanese) can be drawn above the edges of the info panel thus the clip needs to be extended a bit
|
||||
clipRectMin.x -= annotationFontSize;
|
||||
clipRectMin.y -= annotationFontSize;
|
||||
clipRectMax.x += annotationFontSize;
|
||||
clipRectMax.y += annotationFontSize;
|
||||
|
||||
textX += annotationFontSize;
|
||||
textY += annotationFontSize;
|
||||
}
|
||||
|
||||
drawList->PushClipRect(clipRectMin, clipRectMax, false);
|
||||
|
||||
DrawRubyAnnotatedText
|
||||
(
|
||||
g_seuratFont,
|
||||
fontSize,
|
||||
{ clipRectMin.x, clipRectMin.y },
|
||||
IM_COL32(255, 255, 255, 255 * textAlpha),
|
||||
clipRectMax.x - clipRectMin.x,
|
||||
{ textX, textY },
|
||||
lineMargin,
|
||||
descriptionText,
|
||||
0,
|
||||
clipRectMax.x - clipRectMin.x
|
||||
[=](const char* str, ImVec2 pos)
|
||||
{
|
||||
DrawTextBasic(g_seuratFont, fontSize, pos, IM_COL32(255, 255, 255, 255 * textAlpha), str);
|
||||
},
|
||||
[=](const char* str, float size, ImVec2 pos)
|
||||
{
|
||||
DrawTextBasic(g_seuratFont, size, pos, IM_COL32(255, 255, 255, 255 * textAlpha), str);
|
||||
}
|
||||
);
|
||||
|
||||
drawList->PopClipRect();
|
||||
|
||||
drawList->PopClipRect();
|
||||
|
||||
if (g_currentPage == WizardPage::InstallSucceeded)
|
||||
{
|
||||
auto hedgeDevStr = "hedge-dev";
|
||||
|
|
|
@ -272,10 +272,31 @@ void MessageWindow::Draw()
|
|||
|
||||
auto maxWidth = Scale(820);
|
||||
auto fontSize = Scale(28);
|
||||
auto textSize = MeasureCentredParagraph(g_fntSeurat, fontSize, maxWidth, 5, g_text.c_str());
|
||||
|
||||
const auto input = RemoveRubyAnnotations(g_text.c_str());
|
||||
auto lines = Split(input.first.c_str(), g_fntSeurat, fontSize, maxWidth);
|
||||
|
||||
for (auto& line : lines)
|
||||
{
|
||||
line = ReAddRubyAnnotations(line, input.second);
|
||||
}
|
||||
|
||||
auto lineMargin = Config::Language != ELanguage::Japanese ? 5.0f : 5.5f;
|
||||
auto textSize = MeasureCentredParagraph(g_fntSeurat, fontSize, lineMargin, lines);
|
||||
auto textMarginX = Scale(37);
|
||||
auto textMarginY = Scale(45);
|
||||
|
||||
auto textX = centre.x;
|
||||
auto textY = centre.y + Scale(3);
|
||||
|
||||
if (Config::Language == ELanguage::Japanese)
|
||||
{
|
||||
textMarginX -= Scale(2.5f);
|
||||
textMarginY -= Scale(7.5f);
|
||||
|
||||
textY += Scale(lines.size() % 2 == 0 ? 8.5f : 15.5f);
|
||||
}
|
||||
|
||||
bool isController = hid::IsInputDeviceController();
|
||||
bool isKeyboard = hid::g_inputDevice == hid::EInputDevice::Keyboard;
|
||||
|
||||
|
@ -307,19 +328,25 @@ void MessageWindow::Draw()
|
|||
|
||||
if (DrawContainer(g_appearTime, centre, { textSize.x / 2 + textMarginX, textSize.y / 2 + textMarginY }, !g_isControlsVisible))
|
||||
{
|
||||
DrawCentredParagraph
|
||||
DrawRubyAnnotatedText
|
||||
(
|
||||
g_fntSeurat,
|
||||
fontSize,
|
||||
maxWidth,
|
||||
{ centre.x, centre.y + Scale(3) },
|
||||
5,
|
||||
{ textX, textY },
|
||||
lineMargin,
|
||||
g_text.c_str(),
|
||||
|
||||
[=](const char* str, ImVec2 pos)
|
||||
{
|
||||
DrawTextWithShadow(g_fntSeurat, fontSize, pos, IM_COL32(255, 255, 255, 255), str);
|
||||
}
|
||||
},
|
||||
[=](const char* str, float size, ImVec2 pos)
|
||||
{
|
||||
DrawTextWithShadow(g_fntSeurat, size, pos, IM_COL32(255, 255, 255, 255), str, 1.0f);
|
||||
},
|
||||
|
||||
true
|
||||
);
|
||||
|
||||
drawList->PopClipRect();
|
||||
|
|
|
@ -724,6 +724,11 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef<T>* conf
|
|||
auto alpha = fadedOut ? 0.5f : 1.0f;
|
||||
auto textColour = IM_COL32(255, 255, 255, 255 * alpha);
|
||||
|
||||
if (Config::Language == ELanguage::Japanese)
|
||||
{
|
||||
textPos.y += Scale(10.0f);
|
||||
}
|
||||
|
||||
if (g_selectedItem == config)
|
||||
{
|
||||
float prevItemOffset = (g_prevSelectedRowIndex - g_selectedRowIndex) * (optionHeight + optionPadding);
|
||||
|
@ -746,7 +751,27 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef<T>* conf
|
|||
}
|
||||
else
|
||||
{
|
||||
drawList->AddText(g_seuratFont, size, textPos, textColour, configName.c_str(), 0, 0.0f, &textClipRect);
|
||||
drawList->PushClipRect(min, max, true);
|
||||
|
||||
DrawRubyAnnotatedText
|
||||
(
|
||||
g_seuratFont,
|
||||
size,
|
||||
FLT_MAX,
|
||||
textPos,
|
||||
0.0f,
|
||||
configName.c_str(),
|
||||
[=](const char* str, ImVec2 pos)
|
||||
{
|
||||
DrawTextBasic(g_seuratFont, size, pos, textColour, str);
|
||||
},
|
||||
[=](const char* str, float annotationSize, ImVec2 pos)
|
||||
{
|
||||
DrawTextBasic(g_seuratFont, annotationSize, pos, textColour, str);
|
||||
}
|
||||
);
|
||||
|
||||
drawList->PopClipRect();
|
||||
}
|
||||
|
||||
// Right side
|
||||
|
@ -1231,18 +1256,51 @@ static void DrawInfoPanel(ImVec2 infoMin, ImVec2 infoMax)
|
|||
desc += "\n\n" + g_selectedItem->GetValueDescription(Config::Language);
|
||||
}
|
||||
|
||||
auto size = Scale(26.0f);
|
||||
auto fontSize = Scale(28.0f);
|
||||
auto annotationFontSize = fontSize * ANNOTATION_FONT_SIZE_MODIFIER;
|
||||
|
||||
drawList->AddText
|
||||
// Extra padding between the start of the description text and the bottom of the thumbnail
|
||||
float offsetY = Scale(24.0f);
|
||||
|
||||
float textX = clipRectMin.x - Scale(0.5f);
|
||||
float textY = thumbnailMax.y + offsetY;
|
||||
|
||||
if (Config::Language == ELanguage::Japanese)
|
||||
{
|
||||
// Removing some padding of the applied due to the inclusion of annotation for Japanese
|
||||
textY -= Scale(8.0f);
|
||||
|
||||
// The annotation (and thus the Japanese) can be drawn above the edges of the info panel thus the clip needs to be extended a bit
|
||||
clipRectMin.x -= annotationFontSize;
|
||||
clipRectMin.y -= annotationFontSize;
|
||||
clipRectMax.x += annotationFontSize;
|
||||
clipRectMax.y += annotationFontSize;
|
||||
|
||||
textY += annotationFontSize;
|
||||
}
|
||||
|
||||
drawList->PushClipRect(clipRectMin, clipRectMax, false);
|
||||
|
||||
DrawRubyAnnotatedText
|
||||
(
|
||||
g_seuratFont,
|
||||
size,
|
||||
{ clipRectMin.x, thumbnailMax.y + size - 5.0f },
|
||||
IM_COL32_WHITE,
|
||||
fontSize,
|
||||
clipRectMax.x - clipRectMin.x,
|
||||
{ textX, textY },
|
||||
5.0f,
|
||||
desc.c_str(),
|
||||
0,
|
||||
clipRectMax.x - clipRectMin.x
|
||||
|
||||
[=](const char* str, ImVec2 pos)
|
||||
{
|
||||
DrawTextBasic(g_seuratFont, fontSize, pos, IM_COL32(255, 255, 255, 255), str);
|
||||
},
|
||||
[=](const char* str, float size, ImVec2 pos)
|
||||
{
|
||||
DrawTextBasic(g_seuratFont, size, pos, IM_COL32(255, 255, 255, 255), str);
|
||||
}
|
||||
);
|
||||
|
||||
drawList->PopClipRect();
|
||||
}
|
||||
|
||||
ResetProceduralOrigin();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue