Apply category select animation.

This commit is contained in:
Skyth 2024-11-19 17:10:17 +03:00
parent eeb428d9de
commit 37a24b1b32

View file

@ -256,14 +256,19 @@ static constexpr const char* CATEGORIES[] =
}; };
static int32_t g_categoryIndex; static int32_t g_categoryIndex;
static ImVec2 g_categoryAnimMin;
static ImVec2 g_categoryAnimMax;
static int32_t g_firstVisibleRowIndex; static int32_t g_firstVisibleRowIndex;
static int32_t g_prevSelectedRowIndex; static int32_t g_prevSelectedRowIndex;
static int32_t g_selectedRowIndex; static int32_t g_selectedRowIndex;
static double g_rowSelectionTime; static double g_rowSelectionTime;
static bool g_leftWasHeld; static bool g_leftWasHeld;
static bool g_upWasHeld; static bool g_upWasHeld;
static bool g_rightWasHeld; static bool g_rightWasHeld;
static bool g_downWasHeld; static bool g_downWasHeld;
static bool g_lockedOnOption; static bool g_lockedOnOption;
static double g_lastTappedTime; static double g_lastTappedTime;
static double g_lastIncrementTime; static double g_lastIncrementTime;
@ -300,6 +305,16 @@ static void PlaySound(const char* name)
g_userHeap.Free(soundPlayerSharedPtr); g_userHeap.Free(soundPlayerSharedPtr);
} }
static float Lerp(float a, float b, float t)
{
return a + (b - a) * t;
}
static ImVec2 Lerp(const ImVec2& a, const ImVec2& b, float t)
{
return { a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t };
}
static void DrawCategories() static void DrawCategories()
{ {
auto inputState = SWA::CInputState::GetInstance(); auto inputState = SWA::CInputState::GetInstance();
@ -350,6 +365,8 @@ static void DrawCategories()
float tabHeight = gridSize * 4.0f; float tabHeight = gridSize * 4.0f;
float xOffset = ((clipRectMax.x - clipRectMin.x) - tabWidthSum) / 2.0f; float xOffset = ((clipRectMax.x - clipRectMin.x) - tabWidthSum) / 2.0f;
ImVec2 minVec[std::size(CATEGORIES)];
for (size_t i = 0; i < std::size(CATEGORIES); i++) for (size_t i = 0; i < std::size(CATEGORIES); i++)
{ {
ImVec2 min = { clipRectMin.x + xOffset, clipRectMin.y }; ImVec2 min = { clipRectMin.x + xOffset, clipRectMin.y };
@ -358,24 +375,44 @@ static void DrawCategories()
ImVec2 max = { clipRectMin.x + xOffset, clipRectMin.y + tabHeight }; ImVec2 max = { clipRectMin.x + xOffset, clipRectMin.y + tabHeight };
xOffset += tabPadding; xOffset += tabPadding;
uint32_t alpha = 235;
if (g_categoryIndex == i) if (g_categoryIndex == i)
{ {
// Animation interrupted by entering/exiting or resizing the options menu
if (abs(g_categoryAnimMin.y - min.y) > 0.01f || abs(g_categoryAnimMax.y - max.y) > 0.01f)
{
g_categoryAnimMin = min;
g_categoryAnimMax = max;
}
else
{
float animWidth = g_categoryAnimMax.x - g_categoryAnimMin.x;
float width = max.x - min.x;
float height = max.y - min.y;
animWidth = Lerp(animWidth, width, 1.0f - exp(-64.0f * ImGui::GetIO().DeltaTime));
g_categoryAnimMin = Lerp(g_categoryAnimMin, min, 1.0f - exp(-16.0f * ImGui::GetIO().DeltaTime));
g_categoryAnimMax = { g_categoryAnimMin.x + animWidth, g_categoryAnimMin.y + height };
}
SetShaderModifier(IMGUI_SHADER_MODIFIER_SCANLINE_BUTTON); SetShaderModifier(IMGUI_SHADER_MODIFIER_SCANLINE_BUTTON);
drawList->AddRectFilledMultiColor(min, max, IM_COL32(0, 130, 0, 223), IM_COL32(0, 130, 0, 178), IM_COL32(0, 130, 0, 223), IM_COL32(0, 130, 0, 178)); drawList->AddRectFilledMultiColor(g_categoryAnimMin, g_categoryAnimMax, IM_COL32(0, 130, 0, 223), IM_COL32(0, 130, 0, 178), IM_COL32(0, 130, 0, 223), IM_COL32(0, 130, 0, 178));
drawList->AddRectFilledMultiColor(min, max, IM_COL32(0, 0, 0, 13), IM_COL32(0, 0, 0, 0), IM_COL32(0, 0, 0, 55), IM_COL32(0, 0, 0, 6)); drawList->AddRectFilledMultiColor(g_categoryAnimMin, g_categoryAnimMax, IM_COL32(0, 0, 0, 13), IM_COL32(0, 0, 0, 0), IM_COL32(0, 0, 0, 55), IM_COL32(0, 0, 0, 6));
drawList->AddRectFilledMultiColor(min, max, IM_COL32(0, 130, 0, 13), IM_COL32(0, 130, 0, 111), IM_COL32(0, 130, 0, 0), IM_COL32(0, 130, 0, 55)); drawList->AddRectFilledMultiColor(g_categoryAnimMin, g_categoryAnimMax, IM_COL32(0, 130, 0, 13), IM_COL32(0, 130, 0, 111), IM_COL32(0, 130, 0, 0), IM_COL32(0, 130, 0, 55));
SetShaderModifier(IMGUI_SHADER_MODIFIER_NONE); SetShaderModifier(IMGUI_SHADER_MODIFIER_NONE);
} }
else
{
alpha = 128;
}
// Store to draw again later, otherwise the tab background gets drawn on top of text during the animation.
min.x += textPadding; min.x += textPadding;
minVec[i] = min;
}
for (size_t i = 0; i < std::size(CATEGORIES); i++)
{
auto& min = minVec[i];
uint8_t alpha = i == g_categoryIndex ? 235 : 128;
SetGradient( SetGradient(
min, min,
@ -918,8 +955,9 @@ void OptionsMenu::Open(bool stage)
{ {
s_isVisible = true; s_isVisible = true;
s_isStage = stage; s_isStage = stage;
g_categoryIndex = 0; g_categoryIndex = 0;
g_categoryAnimMin = { 0.0f, 0.0f };
g_categoryAnimMax = { 0.0f, 0.0f };
/* Store button state so we can track it later /* Store button state so we can track it later
and prevent the first item being selected. */ and prevent the first item being selected. */