mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2026-04-27 04:41:39 +00:00
achievements_menu: implemented animations and improved navigation
This commit is contained in:
parent
e1fff00bab
commit
279c64c0e0
2 changed files with 195 additions and 80 deletions
|
|
@ -5,8 +5,11 @@
|
||||||
#include <ui/options_menu.h>
|
#include <ui/options_menu.h>
|
||||||
#include <app.h>
|
#include <app.h>
|
||||||
|
|
||||||
float m_ungracefulExitWaitTime = 0.0f;
|
float g_achievementMenuIntroTime = 0.0f;
|
||||||
constexpr float m_ungracefulExitWaitThreshold = 3.0f;
|
constexpr float g_achievementMenuIntroThreshold = 3.0f;
|
||||||
|
float g_achievementMenuOutroTime = 0.0f;
|
||||||
|
constexpr float g_achievementMenuOutroThreshold = 0.53f;
|
||||||
|
bool g_isAchievementMenuOutro = false;
|
||||||
|
|
||||||
void CHudPauseAddOptionsItemMidAsmHook(PPCRegister& pThis)
|
void CHudPauseAddOptionsItemMidAsmHook(PPCRegister& pThis)
|
||||||
{
|
{
|
||||||
|
|
@ -110,20 +113,34 @@ PPC_FUNC(sub_824B0930)
|
||||||
auto pHudPause = (SWA::CHudPause*)g_memory.Translate(ctx.r3.u32);
|
auto pHudPause = (SWA::CHudPause*)g_memory.Translate(ctx.r3.u32);
|
||||||
auto pInputState = SWA::CInputState::GetInstance();
|
auto pInputState = SWA::CInputState::GetInstance();
|
||||||
|
|
||||||
m_ungracefulExitWaitTime += g_deltaTime;
|
g_achievementMenuIntroTime += g_deltaTime;
|
||||||
|
|
||||||
|
if (g_isAchievementMenuOutro)
|
||||||
|
{
|
||||||
|
g_achievementMenuOutroTime += g_deltaTime;
|
||||||
|
|
||||||
|
// Re-open pause menu after achievement menu closes with delay.
|
||||||
|
if (g_achievementMenuOutroTime >= g_achievementMenuOutroThreshold)
|
||||||
|
{
|
||||||
|
GuestToHostFunction<int>(0x824AFD28, pHudPause, 0, 1, 0, 0);
|
||||||
|
|
||||||
|
g_achievementMenuOutroTime = 0;
|
||||||
|
g_isAchievementMenuOutro = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: disable Start button closing menu.
|
// TODO: disable Start button closing menu.
|
||||||
if (AchievementMenu::s_isVisible)
|
if (AchievementMenu::s_isVisible)
|
||||||
{
|
{
|
||||||
// HACK: wait for transition to finish before restoring control.
|
// HACK: wait for transition to finish before restoring control.
|
||||||
if (m_ungracefulExitWaitThreshold >= m_ungracefulExitWaitTime)
|
if (g_achievementMenuIntroThreshold >= g_achievementMenuIntroTime)
|
||||||
__imp__sub_824B0930(ctx, base);
|
__imp__sub_824B0930(ctx, base);
|
||||||
|
|
||||||
if (pInputState->GetPadState().IsTapped(SWA::eKeyState_B))
|
if (pInputState->GetPadState().IsTapped(SWA::eKeyState_B))
|
||||||
{
|
{
|
||||||
AchievementMenu::Close();
|
AchievementMenu::Close();
|
||||||
|
|
||||||
GuestToHostFunction<int>(0x824AFD28, pHudPause, 0, 1, 0, 0);
|
g_isAchievementMenuOutro = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (OptionsMenu::s_isVisible && OptionsMenu::s_isPause)
|
else if (OptionsMenu::s_isVisible && OptionsMenu::s_isPause)
|
||||||
|
|
@ -137,7 +154,7 @@ PPC_FUNC(sub_824B0930)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_ungracefulExitWaitTime = 0.0f;
|
g_achievementMenuIntroTime = 0;
|
||||||
|
|
||||||
__imp__sub_824B0930(ctx, base);
|
__imp__sub_824B0930(ctx, base);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,30 +9,44 @@
|
||||||
#include <app.h>
|
#include <app.h>
|
||||||
#include <exports.h>
|
#include <exports.h>
|
||||||
|
|
||||||
static std::vector<Achievement> m_achievements;
|
constexpr double HEADER_CONTAINER_COMMON_MOTION_START = 0;
|
||||||
|
constexpr double HEADER_CONTAINER_COMMON_MOTION_END = 16;
|
||||||
|
|
||||||
static ImFont* m_fntSeurat;
|
constexpr double CONTENT_CONTAINER_COMMON_MOTION_START = 11;
|
||||||
static ImFont* m_fntNewRodin;
|
constexpr double CONTENT_CONTAINER_COMMON_MOTION_END = 12;
|
||||||
|
|
||||||
static int m_firstVisibleRowIndex;
|
constexpr double SELECTION_CONTAINER_BREATHE = 30;
|
||||||
static int m_prevSelectedRowIndex;
|
|
||||||
static int m_selectedRowIndex;
|
|
||||||
static double m_rowSelectionTime;
|
|
||||||
|
|
||||||
static bool m_upWasHeld;
|
static bool g_isClosing = false;
|
||||||
static bool m_downWasHeld;
|
|
||||||
|
static double g_appearTime = 0;
|
||||||
|
|
||||||
|
static std::vector<Achievement> g_achievements;
|
||||||
|
|
||||||
|
static ImFont* g_fntSeurat;
|
||||||
|
static ImFont* g_fntNewRodin;
|
||||||
|
|
||||||
|
static int g_firstVisibleRowIndex;
|
||||||
|
static int g_selectedRowIndex;
|
||||||
|
static double g_rowSelectionTime;
|
||||||
|
|
||||||
|
static bool g_upWasHeld;
|
||||||
|
static bool g_downWasHeld;
|
||||||
|
static bool g_leftWasHeld;
|
||||||
|
static bool g_rightWasHeld;
|
||||||
|
static bool g_upRSWasHeld;
|
||||||
|
static bool g_downRSWasHeld;
|
||||||
|
|
||||||
static void ResetSelection()
|
static void ResetSelection()
|
||||||
{
|
{
|
||||||
m_firstVisibleRowIndex = 0;
|
g_firstVisibleRowIndex = 0;
|
||||||
m_selectedRowIndex = 0;
|
g_selectedRowIndex = 0;
|
||||||
m_prevSelectedRowIndex = 0;
|
g_rowSelectionTime = ImGui::GetTime();
|
||||||
m_rowSelectionTime = ImGui::GetTime();
|
g_upWasHeld = false;
|
||||||
m_upWasHeld = false;
|
g_downWasHeld = false;
|
||||||
m_downWasHeld = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DrawContainer(ImVec2 min, ImVec2 max, ImU32 gradientTop, ImU32 gradientBottom, float cornerRadius = 25)
|
static void DrawContainer(ImVec2 min, ImVec2 max, ImU32 gradientTop, ImU32 gradientBottom, float alpha = 1, float cornerRadius = 25)
|
||||||
{
|
{
|
||||||
auto drawList = ImGui::GetForegroundDrawList();
|
auto drawList = ImGui::GetForegroundDrawList();
|
||||||
auto vertices = GetPauseContainerVertices(min, max, cornerRadius);
|
auto vertices = GetPauseContainerVertices(min, max, cornerRadius);
|
||||||
|
|
@ -40,10 +54,10 @@ static void DrawContainer(ImVec2 min, ImVec2 max, ImU32 gradientTop, ImU32 gradi
|
||||||
// TODO: add a drop shadow.
|
// TODO: add a drop shadow.
|
||||||
|
|
||||||
SetGradient(min, max, gradientTop, gradientBottom);
|
SetGradient(min, max, gradientTop, gradientBottom);
|
||||||
drawList->AddConvexPolyFilled(vertices.data(), vertices.size(), IM_COL32(255, 255, 255, 255));
|
drawList->AddConvexPolyFilled(vertices.data(), vertices.size(), IM_COL32(255, 255, 255, 255 * alpha));
|
||||||
ResetGradient();
|
ResetGradient();
|
||||||
|
|
||||||
drawList->AddPolyline(vertices.data(), vertices.size(), IM_COL32(247, 247, 247, 255), true, Scale(2.5f));
|
drawList->AddPolyline(vertices.data(), vertices.size(), IM_COL32(247, 247, 247, 255 * alpha), true, Scale(2.5f));
|
||||||
|
|
||||||
for (int i = 0; i < vertices.size(); i++)
|
for (int i = 0; i < vertices.size(); i++)
|
||||||
{
|
{
|
||||||
|
|
@ -51,8 +65,8 @@ static void DrawContainer(ImVec2 min, ImVec2 max, ImU32 gradientTop, ImU32 gradi
|
||||||
vertices[i].y -= Scale(0.2f);
|
vertices[i].y -= Scale(0.2f);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto colLineTop = IM_COL32(165, 170, 165, 230);
|
auto colLineTop = IM_COL32(165, 170, 165, 230 * alpha);
|
||||||
auto colLineBottom = IM_COL32(190, 190, 190, 230);
|
auto colLineBottom = IM_COL32(190, 190, 190, 230 * alpha);
|
||||||
auto lineThickness = Scale(1);
|
auto lineThickness = Scale(1);
|
||||||
|
|
||||||
// Top left corner bottom to top left corner top.
|
// Top left corner bottom to top left corner top.
|
||||||
|
|
@ -80,8 +94,11 @@ static void DrawSelectionContainer(ImVec2 min, ImVec2 max)
|
||||||
auto drawList = ImGui::GetForegroundDrawList();
|
auto drawList = ImGui::GetForegroundDrawList();
|
||||||
auto vertices = GetPauseContainerVertices(min, max, 10);
|
auto vertices = GetPauseContainerVertices(min, max, 10);
|
||||||
|
|
||||||
SetGradient(min, max, IM_COL32(255, 246, 0, 129), IM_COL32(255, 194, 0, 118));
|
static auto breatheStart = ImGui::GetTime();
|
||||||
drawList->AddConvexPolyFilled(vertices.data(), vertices.size(), IM_COL32(255, 255, 255, 255));
|
auto alpha = Lerp(1.0f, 0.75f, (sin((ImGui::GetTime() - breatheStart) * (2.0f * M_PI / (55.0f / 60.0f))) + 1.0f) / 2.0f);
|
||||||
|
|
||||||
|
SetGradient(min, max, IM_COL32(255, 246, 0, 129), IM_COL32(255, 194, 0, 118 * alpha));
|
||||||
|
drawList->AddConvexPolyFilled(vertices.data(), vertices.size(), IM_COL32(255, 255, 255, 255 * alpha));
|
||||||
ResetGradient();
|
ResetGradient();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -89,26 +106,38 @@ static void DrawHeaderContainer(const char* text)
|
||||||
{
|
{
|
||||||
auto drawList = ImGui::GetForegroundDrawList();
|
auto drawList = ImGui::GetForegroundDrawList();
|
||||||
auto fontSize = Scale(26);
|
auto fontSize = Scale(26);
|
||||||
auto textSize = m_fntNewRodin->CalcTextSizeA(fontSize, FLT_MAX, 0, text);
|
auto textSize = g_fntNewRodin->CalcTextSizeA(fontSize, FLT_MAX, 0, text);
|
||||||
auto cornerRadius = 23;
|
auto cornerRadius = 23;
|
||||||
auto textMarginX = Scale(16) + (Scale(cornerRadius) / 2);
|
auto textMarginX = Scale(16) + (Scale(cornerRadius) / 2);
|
||||||
|
|
||||||
ImVec2 min = { Scale(256), Scale(138) };
|
auto motion = ComputeMotion(g_appearTime, HEADER_CONTAINER_COMMON_MOTION_START, HEADER_CONTAINER_COMMON_MOTION_END);
|
||||||
|
|
||||||
|
// Slide animation.
|
||||||
|
auto containerMarginX = g_isClosing
|
||||||
|
? Hermite(256, 156, motion)
|
||||||
|
: Hermite(156, 256, motion);
|
||||||
|
|
||||||
|
// Transparency fade animation.
|
||||||
|
auto alpha = g_isClosing
|
||||||
|
? Hermite(1, 0, motion)
|
||||||
|
: Hermite(0, 1, motion);
|
||||||
|
|
||||||
|
ImVec2 min = { Scale(containerMarginX), Scale(138)};
|
||||||
ImVec2 max = { min.x + textMarginX * 2 + textSize.x, Scale(185) };
|
ImVec2 max = { min.x + textMarginX * 2 + textSize.x, Scale(185) };
|
||||||
|
|
||||||
DrawContainer(min, max, IM_COL32(140, 142, 140, 201), IM_COL32(66, 65, 66, 234), cornerRadius);
|
DrawContainer(min, max, IM_COL32(140, 142, 140, 201), IM_COL32(66, 65, 66, 234), alpha, cornerRadius);
|
||||||
drawList->PopClipRect();
|
drawList->PopClipRect();
|
||||||
|
|
||||||
// TODO: skew this text and apply bevel.
|
// TODO: skew this text and apply bevel.
|
||||||
DrawTextWithOutline<int>
|
DrawTextWithOutline<int>
|
||||||
(
|
(
|
||||||
m_fntNewRodin,
|
g_fntNewRodin,
|
||||||
fontSize,
|
fontSize,
|
||||||
{ /* X */ min.x + textMarginX, /* Y */ min.y + textSize.y / Scale(2) + Scale(2.5f) /* 2.5 = container outline thickness */ },
|
{ /* X */ min.x + textMarginX, /* Y */ min.y + textSize.y / Scale(2) + Scale(2.5f) /* 2.5 = container outline thickness */ },
|
||||||
IM_COL32(255, 255, 255, 255),
|
IM_COL32(255, 255, 255, 255 * alpha),
|
||||||
text,
|
text,
|
||||||
3,
|
3,
|
||||||
IM_COL32(0, 0, 0, 255)
|
IM_COL32(0, 0, 0, 255 * alpha)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -130,14 +159,14 @@ static void DrawAchievement(int rowIndex, float yOffset, Achievement& achievemen
|
||||||
ImVec2 max = { itemMarginX + min.x + itemWidth, min.y + itemHeight };
|
ImVec2 max = { itemMarginX + min.x + itemWidth, min.y + itemHeight };
|
||||||
|
|
||||||
auto icon = g_xdbfTextureCache[achievement.ID];
|
auto icon = g_xdbfTextureCache[achievement.ID];
|
||||||
auto isSelected = rowIndex == m_selectedRowIndex;
|
auto isSelected = rowIndex == g_selectedRowIndex;
|
||||||
|
|
||||||
if (isSelected)
|
if (isSelected)
|
||||||
DrawSelectionContainer(min, max);
|
DrawSelectionContainer(min, max);
|
||||||
|
|
||||||
auto desc = isUnlocked ? achievement.UnlockedDesc.c_str() : achievement.LockedDesc.c_str();
|
auto desc = isUnlocked ? achievement.UnlockedDesc.c_str() : achievement.LockedDesc.c_str();
|
||||||
auto fontSize = Scale(24);
|
auto fontSize = Scale(24);
|
||||||
auto textSize = m_fntSeurat->CalcTextSizeA(fontSize, FLT_MAX, 0, desc);
|
auto textSize = g_fntSeurat->CalcTextSizeA(fontSize, FLT_MAX, 0, desc);
|
||||||
auto textX = min.x + imageMarginX + imageSize + itemMarginX * 2;
|
auto textX = min.x + imageMarginX + imageSize + itemMarginX * 2;
|
||||||
auto textMarqueeX = min.x + imageMarginX + imageSize;
|
auto textMarqueeX = min.x + imageMarginX + imageSize;
|
||||||
auto titleTextY = Scale(20);
|
auto titleTextY = Scale(20);
|
||||||
|
|
@ -168,7 +197,7 @@ static void DrawAchievement(int rowIndex, float yOffset, Achievement& achievemen
|
||||||
// Draw achievement name.
|
// Draw achievement name.
|
||||||
DrawTextWithShadow
|
DrawTextWithShadow
|
||||||
(
|
(
|
||||||
m_fntSeurat,
|
g_fntSeurat,
|
||||||
fontSize,
|
fontSize,
|
||||||
{ textX, min.y + titleTextY },
|
{ textX, min.y + titleTextY },
|
||||||
isUnlocked ? IM_COL32(252, 243, 5, 255) : colLockedText,
|
isUnlocked ? IM_COL32(252, 243, 5, 255) : colLockedText,
|
||||||
|
|
@ -183,14 +212,14 @@ static void DrawAchievement(int rowIndex, float yOffset, Achievement& achievemen
|
||||||
// Draw achievement description with marquee.
|
// Draw achievement description with marquee.
|
||||||
DrawTextWithMarqueeShadow
|
DrawTextWithMarqueeShadow
|
||||||
(
|
(
|
||||||
m_fntSeurat,
|
g_fntSeurat,
|
||||||
fontSize,
|
fontSize,
|
||||||
{ textX, min.y + descTextY },
|
{ textX, min.y + descTextY },
|
||||||
{ textMarqueeX, min.y },
|
{ textMarqueeX, min.y },
|
||||||
max,
|
max,
|
||||||
isUnlocked ? IM_COL32(255, 255, 255, 255) : colLockedText,
|
isUnlocked ? IM_COL32(255, 255, 255, 255) : colLockedText,
|
||||||
desc,
|
desc,
|
||||||
m_rowSelectionTime,
|
g_rowSelectionTime,
|
||||||
0.9,
|
0.9,
|
||||||
250.0,
|
250.0,
|
||||||
shadowOffset,
|
shadowOffset,
|
||||||
|
|
@ -203,7 +232,7 @@ static void DrawAchievement(int rowIndex, float yOffset, Achievement& achievemen
|
||||||
// Draw achievement description.
|
// Draw achievement description.
|
||||||
DrawTextWithShadow
|
DrawTextWithShadow
|
||||||
(
|
(
|
||||||
m_fntSeurat,
|
g_fntSeurat,
|
||||||
fontSize,
|
fontSize,
|
||||||
{ textX, min.y + descTextY },
|
{ textX, min.y + descTextY },
|
||||||
isUnlocked ? IM_COL32(255, 255, 255, 255) : colLockedText,
|
isUnlocked ? IM_COL32(255, 255, 255, 255) : colLockedText,
|
||||||
|
|
@ -221,16 +250,50 @@ static void DrawContentContainer()
|
||||||
{
|
{
|
||||||
auto drawList = ImGui::GetForegroundDrawList();
|
auto drawList = ImGui::GetForegroundDrawList();
|
||||||
|
|
||||||
ImVec2 min = { Scale(256), Scale(192) };
|
// Expand/retract animation.
|
||||||
ImVec2 max = { Scale(1026), Scale(601) };
|
auto motion = ComputeMotion(g_appearTime, CONTENT_CONTAINER_COMMON_MOTION_START, CONTENT_CONTAINER_COMMON_MOTION_END);
|
||||||
|
|
||||||
DrawContainer(min, max, IM_COL32(197, 194, 197, 200), IM_COL32(115, 113, 115, 236));
|
auto minX = g_isClosing
|
||||||
|
? Hermite(256, 306, motion)
|
||||||
|
: Hermite(306, 256, motion);
|
||||||
|
|
||||||
|
auto minY = g_isClosing
|
||||||
|
? Hermite(192, 209, motion)
|
||||||
|
: Hermite(209, 192, motion);
|
||||||
|
|
||||||
|
auto maxX = g_isClosing
|
||||||
|
? Hermite(1026, 973, motion)
|
||||||
|
: Hermite(973, 1026, motion);
|
||||||
|
|
||||||
|
auto maxY = g_isClosing
|
||||||
|
? Hermite(601, 569, motion)
|
||||||
|
: Hermite(569, 601, motion);
|
||||||
|
|
||||||
|
ImVec2 min = { Scale(minX), Scale(minY) };
|
||||||
|
ImVec2 max = { Scale(maxX), Scale(maxY) };
|
||||||
|
|
||||||
|
// Transparency fade animation.
|
||||||
|
auto alpha = g_isClosing
|
||||||
|
? Hermite(1, 0, motion)
|
||||||
|
: Hermite(0, 1, motion);
|
||||||
|
|
||||||
|
DrawContainer(min, max, IM_COL32(197, 194, 197, 200), IM_COL32(115, 113, 115, 236), alpha);
|
||||||
|
|
||||||
|
if (motion < 1.0f)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (g_isClosing)
|
||||||
|
{
|
||||||
|
AchievementMenu::s_isVisible = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto clipRectMin = drawList->GetClipRectMin();
|
auto clipRectMin = drawList->GetClipRectMin();
|
||||||
auto clipRectMax = drawList->GetClipRectMax();
|
auto clipRectMax = drawList->GetClipRectMax();
|
||||||
|
|
||||||
auto itemHeight = Scale(94);
|
auto itemHeight = Scale(94);
|
||||||
auto yOffset = -m_firstVisibleRowIndex * itemHeight + Scale(2);
|
auto yOffset = -g_firstVisibleRowIndex * itemHeight + Scale(2);
|
||||||
auto rowCount = 0;
|
auto rowCount = 0;
|
||||||
|
|
||||||
// Draw separators.
|
// Draw separators.
|
||||||
|
|
@ -247,13 +310,13 @@ static void DrawContentContainer()
|
||||||
drawList->AddLine({ lineMin.x, lineMin.y + Scale(1) }, { lineMax.x, lineMax.y + Scale(1) }, IM_COL32(143, 148, 143, 255));
|
drawList->AddLine({ lineMin.x, lineMin.y + Scale(1) }, { lineMax.x, lineMax.y + Scale(1) }, IM_COL32(143, 148, 143, 255));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto achievement : m_achievements)
|
for (auto achievement : g_achievements)
|
||||||
{
|
{
|
||||||
if (AchievementData::IsUnlocked(achievement.ID))
|
if (AchievementData::IsUnlocked(achievement.ID))
|
||||||
DrawAchievement(rowCount++, yOffset, achievement, true);
|
DrawAchievement(rowCount++, yOffset, achievement, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto achievement : m_achievements)
|
for (auto achievement : g_achievements)
|
||||||
{
|
{
|
||||||
if (!AchievementData::IsUnlocked(achievement.ID))
|
if (!AchievementData::IsUnlocked(achievement.ID))
|
||||||
DrawAchievement(rowCount++, yOffset, achievement, false);
|
DrawAchievement(rowCount++, yOffset, achievement, false);
|
||||||
|
|
@ -267,52 +330,81 @@ static void DrawContentContainer()
|
||||||
bool downIsHeld = inputState->GetPadState().IsDown(SWA::eKeyState_DpadDown) ||
|
bool downIsHeld = inputState->GetPadState().IsDown(SWA::eKeyState_DpadDown) ||
|
||||||
inputState->GetPadState().LeftStickVertical < -0.5f;
|
inputState->GetPadState().LeftStickVertical < -0.5f;
|
||||||
|
|
||||||
bool scrollUp = !m_upWasHeld && upIsHeld;
|
bool leftIsHeld = inputState->GetPadState().IsDown(SWA::eKeyState_DpadLeft) ||
|
||||||
bool scrollDown = !m_downWasHeld && downIsHeld;
|
inputState->GetPadState().LeftStickHorizontal < -0.5f;
|
||||||
|
|
||||||
int prevSelectedRowIndex = m_selectedRowIndex;
|
bool rightIsHeld = inputState->GetPadState().IsDown(SWA::eKeyState_DpadRight) ||
|
||||||
|
inputState->GetPadState().LeftStickHorizontal > 0.5f;
|
||||||
|
|
||||||
|
bool upRSIsHeld = inputState->GetPadState().RightStickVertical > 0.5f;
|
||||||
|
bool downRSIsHeld = inputState->GetPadState().RightStickVertical < -0.5f;
|
||||||
|
|
||||||
|
bool isReachedTop = g_selectedRowIndex == 0;
|
||||||
|
bool isReachedBottom = g_selectedRowIndex == rowCount - 1;
|
||||||
|
|
||||||
|
bool scrollUp = !g_upWasHeld && upIsHeld;
|
||||||
|
bool scrollDown = !g_downWasHeld && downIsHeld;
|
||||||
|
bool scrollPageUp = !g_leftWasHeld && leftIsHeld && !isReachedTop;
|
||||||
|
bool scrollPageDown = !g_rightWasHeld && rightIsHeld && !isReachedBottom;
|
||||||
|
bool jumpToTop = !g_upRSWasHeld && upRSIsHeld && !isReachedTop;
|
||||||
|
bool jumpToBottom = !g_downRSWasHeld && downRSIsHeld && !isReachedBottom;
|
||||||
|
|
||||||
|
int prevSelectedRowIndex = g_selectedRowIndex;
|
||||||
|
|
||||||
if (scrollUp)
|
if (scrollUp)
|
||||||
{
|
{
|
||||||
--m_selectedRowIndex;
|
--g_selectedRowIndex;
|
||||||
if (m_selectedRowIndex < 0)
|
if (g_selectedRowIndex < 0)
|
||||||
m_selectedRowIndex = rowCount - 1;
|
g_selectedRowIndex = rowCount - 1;
|
||||||
}
|
}
|
||||||
else if (scrollDown)
|
else if (scrollDown)
|
||||||
{
|
{
|
||||||
++m_selectedRowIndex;
|
++g_selectedRowIndex;
|
||||||
if (m_selectedRowIndex >= rowCount)
|
if (g_selectedRowIndex >= rowCount)
|
||||||
m_selectedRowIndex = 0;
|
g_selectedRowIndex = 0;
|
||||||
|
}
|
||||||
|
else if (scrollPageUp)
|
||||||
|
{
|
||||||
|
g_selectedRowIndex -= 3;
|
||||||
|
if (g_selectedRowIndex < 0)
|
||||||
|
g_selectedRowIndex = 0;
|
||||||
|
}
|
||||||
|
else if (scrollPageDown)
|
||||||
|
{
|
||||||
|
g_selectedRowIndex += 3;
|
||||||
|
if (g_selectedRowIndex >= rowCount)
|
||||||
|
g_selectedRowIndex = rowCount - 1;
|
||||||
|
}
|
||||||
|
else if (jumpToTop)
|
||||||
|
{
|
||||||
|
g_selectedRowIndex = 0;
|
||||||
|
}
|
||||||
|
else if (jumpToBottom)
|
||||||
|
{
|
||||||
|
g_selectedRowIndex = rowCount - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scrollUp || scrollDown)
|
// lol
|
||||||
|
if (scrollUp || scrollDown || scrollPageUp || scrollPageDown || jumpToTop || jumpToBottom)
|
||||||
{
|
{
|
||||||
m_rowSelectionTime = ImGui::GetTime();
|
g_rowSelectionTime = ImGui::GetTime();
|
||||||
m_prevSelectedRowIndex = prevSelectedRowIndex;
|
|
||||||
Game_PlaySound("sys_actstg_pausecursor");
|
Game_PlaySound("sys_actstg_pausecursor");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_upWasHeld = upIsHeld;
|
g_upWasHeld = upIsHeld;
|
||||||
m_downWasHeld = downIsHeld;
|
g_downWasHeld = downIsHeld;
|
||||||
|
g_leftWasHeld = leftIsHeld;
|
||||||
|
g_rightWasHeld = rightIsHeld;
|
||||||
|
g_upRSWasHeld = upRSIsHeld;
|
||||||
|
g_downRSWasHeld = downRSIsHeld;
|
||||||
|
|
||||||
int visibleRowCount = int(floor((clipRectMax.y - clipRectMin.y) / itemHeight));
|
int visibleRowCount = int(floor((clipRectMax.y - clipRectMin.y) / itemHeight));
|
||||||
|
|
||||||
bool disableMoveAnimation = false;
|
if (g_firstVisibleRowIndex > g_selectedRowIndex)
|
||||||
|
g_firstVisibleRowIndex = g_selectedRowIndex;
|
||||||
|
|
||||||
if (m_firstVisibleRowIndex > m_selectedRowIndex)
|
if (g_firstVisibleRowIndex + visibleRowCount - 1 < g_selectedRowIndex)
|
||||||
{
|
g_firstVisibleRowIndex = std::max(0, g_selectedRowIndex - visibleRowCount + 1);
|
||||||
m_firstVisibleRowIndex = m_selectedRowIndex;
|
|
||||||
disableMoveAnimation = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_firstVisibleRowIndex + visibleRowCount - 1 < m_selectedRowIndex)
|
|
||||||
{
|
|
||||||
m_firstVisibleRowIndex = std::max(0, m_selectedRowIndex - visibleRowCount + 1);
|
|
||||||
disableMoveAnimation = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (disableMoveAnimation)
|
|
||||||
m_prevSelectedRowIndex = m_selectedRowIndex;
|
|
||||||
|
|
||||||
// Pop clip rect from DrawContentContainer
|
// Pop clip rect from DrawContentContainer
|
||||||
drawList->PopClipRect();
|
drawList->PopClipRect();
|
||||||
|
|
@ -323,7 +415,7 @@ static void DrawContentContainer()
|
||||||
float cornerRadius = Scale(25.0f);
|
float cornerRadius = Scale(25.0f);
|
||||||
float totalHeight = (clipRectMax.y - clipRectMin.y - cornerRadius) - Scale(3.0f);
|
float totalHeight = (clipRectMax.y - clipRectMin.y - cornerRadius) - Scale(3.0f);
|
||||||
float heightRatio = float(visibleRowCount) / float(rowCount);
|
float heightRatio = float(visibleRowCount) / float(rowCount);
|
||||||
float offsetRatio = float(m_firstVisibleRowIndex) / float(rowCount);
|
float offsetRatio = float(g_firstVisibleRowIndex) / float(rowCount);
|
||||||
float offsetX = clipRectMax.x - Scale(31.0f);
|
float offsetX = clipRectMax.x - Scale(31.0f);
|
||||||
float offsetY = offsetRatio * totalHeight + clipRectMin.y + Scale(4.0f);
|
float offsetY = offsetRatio * totalHeight + clipRectMin.y + Scale(4.0f);
|
||||||
float lineThickness = Scale(1.0f);
|
float lineThickness = Scale(1.0f);
|
||||||
|
|
@ -377,10 +469,10 @@ void AchievementMenu::Init()
|
||||||
|
|
||||||
constexpr float FONT_SCALE = 2.0f;
|
constexpr float FONT_SCALE = 2.0f;
|
||||||
|
|
||||||
m_fntSeurat = io.Fonts->AddFontFromFileTTF("FOT-SeuratPro-M.otf", 24.0f * FONT_SCALE);
|
g_fntSeurat = io.Fonts->AddFontFromFileTTF("FOT-SeuratPro-M.otf", 24.0f * FONT_SCALE);
|
||||||
m_fntNewRodin = io.Fonts->AddFontFromFileTTF("FOT-NewRodinPro-UB.otf", 20.0f * FONT_SCALE);
|
g_fntNewRodin = io.Fonts->AddFontFromFileTTF("FOT-NewRodinPro-UB.otf", 20.0f * FONT_SCALE);
|
||||||
|
|
||||||
m_achievements = g_xdbfWrapper.GetAchievements((EXDBFLanguage)Config::Language.Value);
|
g_achievements = g_xdbfWrapper.GetAchievements((EXDBFLanguage)Config::Language.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AchievementMenu::Draw()
|
void AchievementMenu::Draw()
|
||||||
|
|
@ -395,6 +487,8 @@ void AchievementMenu::Draw()
|
||||||
void AchievementMenu::Open()
|
void AchievementMenu::Open()
|
||||||
{
|
{
|
||||||
s_isVisible = true;
|
s_isVisible = true;
|
||||||
|
g_isClosing = false;
|
||||||
|
g_appearTime = ImGui::GetTime();
|
||||||
|
|
||||||
ResetSelection();
|
ResetSelection();
|
||||||
Game_PlaySound("sys_actstg_pausewinopen");
|
Game_PlaySound("sys_actstg_pausewinopen");
|
||||||
|
|
@ -402,7 +496,11 @@ void AchievementMenu::Open()
|
||||||
|
|
||||||
void AchievementMenu::Close()
|
void AchievementMenu::Close()
|
||||||
{
|
{
|
||||||
s_isVisible = false;
|
if (!g_isClosing)
|
||||||
|
{
|
||||||
|
g_appearTime = ImGui::GetTime();
|
||||||
|
g_isClosing = true;
|
||||||
|
}
|
||||||
|
|
||||||
Game_PlaySound("sys_actstg_pausewinclose");
|
Game_PlaySound("sys_actstg_pausewinclose");
|
||||||
Game_PlaySound("sys_actstg_pausecansel");
|
Game_PlaySound("sys_actstg_pausecansel");
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue