mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2025-12-19 14:32:19 +00:00
options_menu: implemented value switch animations (#248)
This commit is contained in:
parent
21c1d36836
commit
ed0aeb3b7d
1 changed files with 146 additions and 28 deletions
|
|
@ -27,6 +27,8 @@ static constexpr double MILES_ELECTRIC_FOREGROUND_FADE_DURATION = 6.0;
|
||||||
static constexpr double MILES_ELECTRIC_FOREGROUND_FADE_IN_TIME = MILES_ELECTRIC_SCALE_DURATION - 2.0;
|
static constexpr double MILES_ELECTRIC_FOREGROUND_FADE_IN_TIME = MILES_ELECTRIC_SCALE_DURATION - 2.0;
|
||||||
static constexpr double MILES_ELECTRIC_FOREGROUND_FADE_OUT_TIME = MILES_ELECTRIC_FOREGROUND_FADE_IN_TIME + MILES_ELECTRIC_FOREGROUND_FADE_DURATION;
|
static constexpr double MILES_ELECTRIC_FOREGROUND_FADE_OUT_TIME = MILES_ELECTRIC_FOREGROUND_FADE_IN_TIME + MILES_ELECTRIC_FOREGROUND_FADE_DURATION;
|
||||||
|
|
||||||
|
static constexpr double VALUE_SLIDER_INTRO_DURATION = 20.0;
|
||||||
|
|
||||||
static constexpr double CONTAINER_LINE_ANIMATION_DURATION = 8.0;
|
static constexpr double CONTAINER_LINE_ANIMATION_DURATION = 8.0;
|
||||||
|
|
||||||
static constexpr double CONTAINER_OUTER_TIME = CONTAINER_LINE_ANIMATION_DURATION + 8.0; // 8 frame delay
|
static constexpr double CONTAINER_OUTER_TIME = CONTAINER_LINE_ANIMATION_DURATION + 8.0; // 8 frame delay
|
||||||
|
|
@ -70,6 +72,7 @@ static bool g_rightWasHeld;
|
||||||
static bool g_downWasHeld;
|
static bool g_downWasHeld;
|
||||||
|
|
||||||
static bool g_lockedOnOption;
|
static bool g_lockedOnOption;
|
||||||
|
static double g_lockedOnTime;
|
||||||
static double g_lastTappedTime;
|
static double g_lastTappedTime;
|
||||||
static double g_lastIncrementTime;
|
static double g_lastIncrementTime;
|
||||||
static double g_lastIncrementSoundTime;
|
static double g_lastIncrementSoundTime;
|
||||||
|
|
@ -589,6 +592,132 @@ static bool DrawCategories()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void DrawSelectionArrows(ImVec2 min, ImVec2 max, bool isLeftTapped, bool isRightTapped, bool isSlider)
|
||||||
|
{
|
||||||
|
static constexpr double sizeMotionDuration = 16.0;
|
||||||
|
|
||||||
|
static bool isLeftArrowMotion = false;
|
||||||
|
static bool isRightArrowMotion = false;
|
||||||
|
|
||||||
|
auto drawList = ImGui::GetForegroundDrawList();
|
||||||
|
auto gridSize = Scale(GRID_SIZE);
|
||||||
|
auto width = gridSize * 2.5f;
|
||||||
|
auto padding = gridSize;
|
||||||
|
|
||||||
|
auto bgMotion = (isLeftArrowMotion || isRightArrowMotion)
|
||||||
|
? ComputeMotion(g_lastTappedTime, 8.0, sizeMotionDuration)
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
if (isLeftTapped)
|
||||||
|
{
|
||||||
|
isLeftArrowMotion = true;
|
||||||
|
isRightArrowMotion = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isRightTapped)
|
||||||
|
{
|
||||||
|
isLeftArrowMotion = false;
|
||||||
|
isRightArrowMotion = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bgMotion >= 1.0 || isSlider)
|
||||||
|
{
|
||||||
|
isLeftArrowMotion = false;
|
||||||
|
isRightArrowMotion = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto getBgColour = [&](bool isAnim) -> ImU32
|
||||||
|
{
|
||||||
|
return IM_COL32(0, 97, 0, Lerp(96, 255, isAnim ? bgMotion : 1));
|
||||||
|
};
|
||||||
|
|
||||||
|
auto bgLeftColour = getBgColour(isLeftArrowMotion);
|
||||||
|
auto bgRightColour = getBgColour(isRightArrowMotion);
|
||||||
|
|
||||||
|
auto invertMotion = isSlider ? ComputeMotion(g_lockedOnTime, 0, VALUE_SLIDER_INTRO_DURATION) : 0;
|
||||||
|
auto invertMotionX = invertMotion > 0.5 ? 1.0 : 0.0; // Arrow side point invert animation
|
||||||
|
|
||||||
|
auto xAdd = Hermite(0, Scale(10), sin(invertMotion * M_PI)); // Arrow jump animation
|
||||||
|
auto y = (min.y + max.y) / 2.0f;
|
||||||
|
|
||||||
|
// Left triangle vertices
|
||||||
|
auto leftX = Lerp(min.x - padding, min.x - padding - width, invertMotionX) - xAdd;
|
||||||
|
auto leftV1Y = Hermite(min.y, max.y, invertMotion);
|
||||||
|
auto leftV2Y = Hermite(max.y, min.y, invertMotion);
|
||||||
|
auto leftV3X = Hermite(min.x - padding - width, min.x - padding, invertMotionX) - xAdd;
|
||||||
|
|
||||||
|
// Right triangle vertices
|
||||||
|
auto rightX = Lerp(max.x + padding, max.x + padding + width, invertMotionX) + xAdd;
|
||||||
|
auto rightV1Y = Hermite(max.y, min.y, invertMotion);
|
||||||
|
auto rightV2Y = Hermite(min.y, max.y, invertMotion);
|
||||||
|
auto rightV3X = Hermite(max.x + padding + width, max.x + padding, invertMotionX) + xAdd;
|
||||||
|
|
||||||
|
auto drawLeftArrow = [&](ImU32 col)
|
||||||
|
{
|
||||||
|
drawList->AddTriangleFilled({ leftX, leftV1Y }, { leftX, leftV2Y }, { leftV3X, y }, col);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto drawRightArrow = [&](ImU32 col)
|
||||||
|
{
|
||||||
|
drawList->AddTriangleFilled({ rightX, rightV1Y }, { rightX, rightV2Y }, { rightV3X, y }, col);
|
||||||
|
};
|
||||||
|
|
||||||
|
drawLeftArrow(bgLeftColour);
|
||||||
|
drawRightArrow(bgRightColour);
|
||||||
|
|
||||||
|
// Additive gradient colours
|
||||||
|
auto c0 = IM_COL32(255, 0, 255, 255);
|
||||||
|
auto c1 = IM_COL32(255, 128, 255, 255);
|
||||||
|
|
||||||
|
SetAdditive(true);
|
||||||
|
|
||||||
|
// Apply additive gradients
|
||||||
|
SetGradient({ leftX, leftV1Y }, { leftV3X, y }, c0, c1, c1, c0);
|
||||||
|
drawLeftArrow(bgLeftColour);
|
||||||
|
SetGradient({ rightX, rightV1Y }, { rightV3X, y }, c0, c1, c1, c0);
|
||||||
|
drawRightArrow(bgRightColour);
|
||||||
|
ResetGradient();
|
||||||
|
|
||||||
|
if (isSlider)
|
||||||
|
{
|
||||||
|
auto col = IM_COL32(0, 97, 0, 255 * invertMotion);
|
||||||
|
|
||||||
|
drawLeftArrow(col);
|
||||||
|
drawRightArrow(col);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto fgMotion = ComputeMotion(g_lastTappedTime, 0, sizeMotionDuration);
|
||||||
|
auto fgMotionSine = sin(fgMotion * M_PI);
|
||||||
|
auto fgScale = Lerp(0, Scale(4), fgMotionSine);
|
||||||
|
auto fgColour = IM_COL32(0, 97, 0, 255 * fgMotionSine);
|
||||||
|
|
||||||
|
if (isLeftArrowMotion)
|
||||||
|
{
|
||||||
|
drawList->AddTriangleFilled
|
||||||
|
(
|
||||||
|
{ min.x - padding, min.y - fgScale },
|
||||||
|
{ min.x - padding, max.y + fgScale },
|
||||||
|
{ min.x - padding - width - (fgScale + Scale(2)), (min.y + max.y) / 2.0f },
|
||||||
|
fgColour
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isRightArrowMotion)
|
||||||
|
{
|
||||||
|
drawList->AddTriangleFilled
|
||||||
|
(
|
||||||
|
{ max.x + padding, max.y + fgScale },
|
||||||
|
{ max.x + padding, min.y - fgScale },
|
||||||
|
{ max.x + padding + width + (fgScale + Scale(2)), (min.y + max.y) / 2.0f },
|
||||||
|
fgColour
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SetAdditive(false);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef<T>* config,
|
static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef<T>* config,
|
||||||
bool isAccessible, std::string* inaccessibleReason = nullptr,
|
bool isAccessible, std::string* inaccessibleReason = nullptr,
|
||||||
|
|
@ -601,15 +730,15 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef<T>* conf
|
||||||
|
|
||||||
constexpr float OPTION_NARROW_GRID_COUNT = 36.0f;
|
constexpr float OPTION_NARROW_GRID_COUNT = 36.0f;
|
||||||
constexpr float OPTION_WIDE_GRID_COUNT = 54.0f;
|
constexpr float OPTION_WIDE_GRID_COUNT = 54.0f;
|
||||||
|
constexpr bool IS_SLIDER_TYPE = std::is_same_v<T, float> || std::is_same_v<T, int32_t>;
|
||||||
|
|
||||||
|
auto isValueSlider = IS_SLIDER_TYPE && isSlider;
|
||||||
auto gridSize = Scale(GRID_SIZE);
|
auto gridSize = Scale(GRID_SIZE);
|
||||||
auto optionWidth = gridSize * floor(Lerp(OPTION_NARROW_GRID_COUNT, OPTION_WIDE_GRID_COUNT, g_aspectRatioNarrowScale));
|
auto optionWidth = gridSize * floor(Lerp(OPTION_NARROW_GRID_COUNT, OPTION_WIDE_GRID_COUNT, g_aspectRatioNarrowScale));
|
||||||
auto optionHeight = gridSize * 5.5f;
|
auto optionHeight = gridSize * 5.5f;
|
||||||
auto optionPadding = gridSize * 0.5f;
|
auto optionPadding = gridSize * 0.5f;
|
||||||
auto valueWidth = Scale(192.0f);
|
auto valueWidth = Scale(192.0f);
|
||||||
auto valueHeight = gridSize * 3.0f;
|
auto valueHeight = gridSize * 3.0f;
|
||||||
auto triangleWidth = gridSize * 2.5f;
|
|
||||||
auto trianglePadding = gridSize;
|
|
||||||
|
|
||||||
// Left side
|
// Left side
|
||||||
ImVec2 min = { clipRectMin.x, clipRectMin.y + (optionHeight + optionPadding) * rowIndex + yOffset };
|
ImVec2 min = { clipRectMin.x, clipRectMin.y + (optionHeight + optionPadding) * rowIndex + yOffset };
|
||||||
|
|
@ -623,6 +752,7 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef<T>* conf
|
||||||
ImVec4 textClipRect = { min.x, min.y, max.x, max.y };
|
ImVec4 textClipRect = { min.x, min.y, max.x, max.y };
|
||||||
|
|
||||||
bool lockedOnOption = false;
|
bool lockedOnOption = false;
|
||||||
|
|
||||||
if (g_selectedRowIndex == rowIndex)
|
if (g_selectedRowIndex == rowIndex)
|
||||||
{
|
{
|
||||||
g_selectedItem = config;
|
g_selectedItem = config;
|
||||||
|
|
@ -657,6 +787,7 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef<T>* conf
|
||||||
|
|
||||||
if (g_lockedOnOption)
|
if (g_lockedOnOption)
|
||||||
{
|
{
|
||||||
|
g_lockedOnTime = ImGui::GetTime();
|
||||||
g_leftWasHeld = false;
|
g_leftWasHeld = false;
|
||||||
g_rightWasHeld = false;
|
g_rightWasHeld = false;
|
||||||
|
|
||||||
|
|
@ -725,9 +856,7 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef<T>* conf
|
||||||
auto textColour = IM_COL32(255, 255, 255, 255 * alpha);
|
auto textColour = IM_COL32(255, 255, 255, 255 * alpha);
|
||||||
|
|
||||||
if (Config::Language == ELanguage::Japanese)
|
if (Config::Language == ELanguage::Japanese)
|
||||||
{
|
|
||||||
textPos.y += Scale(10.0f);
|
textPos.y += Scale(10.0f);
|
||||||
}
|
|
||||||
|
|
||||||
if (g_selectedItem == config)
|
if (g_selectedItem == config)
|
||||||
{
|
{
|
||||||
|
|
@ -788,12 +917,19 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef<T>* conf
|
||||||
{
|
{
|
||||||
if constexpr (std::is_same_v<T, float> || std::is_same_v<T, int32_t>)
|
if constexpr (std::is_same_v<T, float> || std::is_same_v<T, int32_t>)
|
||||||
{
|
{
|
||||||
|
if (lockedOnOption)
|
||||||
|
{
|
||||||
|
SetAdditive(true);
|
||||||
|
drawList->AddRectFilled(min, max, IM_COL32(192, 192, 0, 96 * ComputeMotion(g_lockedOnTime, 0, VALUE_SLIDER_INTRO_DURATION)));
|
||||||
|
SetAdditive(false);
|
||||||
|
}
|
||||||
|
|
||||||
// Inner container of slider
|
// Inner container of slider
|
||||||
const uint32_t innerColor0 = IM_COL32(0, 65, 0, 255 * alpha);
|
const uint32_t innerColor0 = IM_COL32(0, 65, 0, 255 * alpha);
|
||||||
const uint32_t innerColor1 = IM_COL32(0, 32, 0, 255 * alpha);
|
const uint32_t innerColor1 = IM_COL32(0, 32, 0, 255 * alpha);
|
||||||
|
|
||||||
float xPadding = Scale(6.0f);
|
float xPadding = Scale(6);
|
||||||
float yPadding = Scale(3.0f);
|
float yPadding = Scale(3);
|
||||||
|
|
||||||
drawList->AddRectFilledMultiColor
|
drawList->AddRectFilledMultiColor
|
||||||
(
|
(
|
||||||
|
|
@ -809,8 +945,8 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef<T>* conf
|
||||||
const uint32_t sliderColor0 = IM_COL32(57, 241, 0, 255 * alpha);
|
const uint32_t sliderColor0 = IM_COL32(57, 241, 0, 255 * alpha);
|
||||||
const uint32_t sliderColor1 = IM_COL32(2, 106, 0, 255 * alpha);
|
const uint32_t sliderColor1 = IM_COL32(2, 106, 0, 255 * alpha);
|
||||||
|
|
||||||
xPadding += Scale(1.0f);
|
xPadding += Scale(2);
|
||||||
yPadding += Scale(1.0f);
|
yPadding += Scale(2);
|
||||||
|
|
||||||
ImVec2 sliderMin = { min.x + xPadding, min.y + yPadding };
|
ImVec2 sliderMin = { min.x + xPadding, min.y + yPadding };
|
||||||
ImVec2 sliderMax = { max.x - xPadding, max.y - yPadding };
|
ImVec2 sliderMax = { max.x - xPadding, max.y - yPadding };
|
||||||
|
|
@ -835,26 +971,6 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef<T>* conf
|
||||||
// Selection triangles
|
// Selection triangles
|
||||||
if (lockedOnOption)
|
if (lockedOnOption)
|
||||||
{
|
{
|
||||||
constexpr uint32_t COLOR = IM_COL32(0, 97, 0, 255);
|
|
||||||
|
|
||||||
// Left
|
|
||||||
drawList->AddTriangleFilled
|
|
||||||
(
|
|
||||||
{ min.x - trianglePadding, min.y },
|
|
||||||
{ min.x - trianglePadding, max.y },
|
|
||||||
{ min.x - trianglePadding - triangleWidth, (min.y + max.y) / 2.0f },
|
|
||||||
COLOR
|
|
||||||
);
|
|
||||||
|
|
||||||
// Right
|
|
||||||
drawList->AddTriangleFilled
|
|
||||||
(
|
|
||||||
{ max.x + trianglePadding, max.y },
|
|
||||||
{ max.x + trianglePadding, min.y },
|
|
||||||
{ max.x + trianglePadding + triangleWidth, (min.y + max.y) / 2.0f },
|
|
||||||
COLOR
|
|
||||||
);
|
|
||||||
|
|
||||||
bool leftIsHeld = padState.IsDown(SWA::eKeyState_DpadLeft) || padState.LeftStickHorizontal < -0.5f;
|
bool leftIsHeld = padState.IsDown(SWA::eKeyState_DpadLeft) || padState.LeftStickHorizontal < -0.5f;
|
||||||
bool rightIsHeld = padState.IsDown(SWA::eKeyState_DpadRight) || padState.LeftStickHorizontal > 0.5f;
|
bool rightIsHeld = padState.IsDown(SWA::eKeyState_DpadRight) || padState.LeftStickHorizontal > 0.5f;
|
||||||
|
|
||||||
|
|
@ -872,6 +988,8 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef<T>* conf
|
||||||
g_leftWasHeld = leftIsHeld;
|
g_leftWasHeld = leftIsHeld;
|
||||||
g_rightWasHeld = rightIsHeld;
|
g_rightWasHeld = rightIsHeld;
|
||||||
|
|
||||||
|
DrawSelectionArrows(min, max, leftTapped, rightTapped, isValueSlider);
|
||||||
|
|
||||||
if constexpr (std::is_enum_v<T>)
|
if constexpr (std::is_enum_v<T>)
|
||||||
{
|
{
|
||||||
auto it = config->EnumTemplateReverse.find(config->Value);
|
auto it = config->EnumTemplateReverse.find(config->Value);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue