diff --git a/profiles/cclcc/hud/titlemenu.lua b/profiles/cclcc/hud/titlemenu.lua index 6a18d1ad..d0ad213a 100644 --- a/profiles/cclcc/hud/titlemenu.lua +++ b/profiles/cclcc/hud/titlemenu.lua @@ -7,8 +7,8 @@ root.TitleMenu = { PressToStartAnimDurationOut = 0.6, PrimaryFadeInDuration = 0.7, PrimaryFadeOutDuration = 0.7, - SecondaryFadeInDuration = 0.512, - SecondaryFadeOutDuration = 0.512, + SecondaryFadeInDuration = 0.4, + SecondaryFadeOutDuration = 0.4, SlideItemsAnimationDurationIn = 0.5, SlideItemsAnimationDurationOut = 0.5, PressToStartSprite = "TitleMenuPressToStart", diff --git a/src/games/cclcc/titlemenu.cpp b/src/games/cclcc/titlemenu.cpp index ba56a6b6..b1fec75d 100644 --- a/src/games/cclcc/titlemenu.cpp +++ b/src/games/cclcc/titlemenu.cpp @@ -147,6 +147,8 @@ TitleMenu::TitleMenu() { // Start menu items offscreen MainItems->Move({-Profile::DesignWidth / 2, 0.0f}); + ContinueItems->Move({-Profile::DesignWidth / 4, 0.0f}); + ExtraItems->Move({-Profile::DesignWidth / 4, 0.0f}); PressToStartAnimation.DurationIn = PressToStartAnimDurationIn; PressToStartAnimation.DurationOut = PressToStartAnimDurationOut; @@ -193,15 +195,40 @@ void TitleMenu::Hide() { } void TitleMenu::UpdateInput() { - Menu::UpdateInput(); - if (CurrentSubMenu) { + if (IsFocused && MainItems->HasFocus) { + TitleButton* currentFocus = + static_cast(CurrentlyFocusedElement); + + auto changeInput = [&](int buttonMask, UI::FocusDirection dir) { + if (PADinputButtonWentDown & buttonMask) { + LastFocusedButton = static_cast(CurrentlyFocusedElement); + LastFocusedButton->HighlightAnimation.StartOut(true); + AdvanceFocus(dir); + currentFocus = static_cast(CurrentlyFocusedElement); + currentFocus->HighlightAnimation.StartIn(true); + } + }; + if (CurrentSubMenu || + currentFocus && currentFocus->HighlightAnimation.State == AS_Stopped) { + changeInput(PAD1DOWN, FDIR_DOWN); + changeInput(PAD1UP, FDIR_UP); + changeInput(PAD1RIGHT, FDIR_RIGHT); + changeInput(PAD1LEFT, FDIR_LEFT); + } + } + + if (CurrentSubMenu && SecondaryFadeAnimation.IsIn()) { if ((PADinputButtonWentDown & PAD1B || PADinputMouseWentDown & PAD1B) && CurrentSubMenu->IsShown && CurrentSubMenu->HasFocus) { if (CurrentSubMenu == ContinueItems) { - HideContinueItems(); + SecondaryFadeAnimation.StartOut(); + ContinueItems->Move(glm::vec2(-Profile::DesignWidth / 4, 0.0f), + SecondaryFadeAnimation.DurationOut); } if (CurrentSubMenu == ExtraItems) { - HideExtraItems(); + SecondaryFadeAnimation.StartOut(); + ExtraItems->Move(glm::vec2(-Profile::DesignWidth / 4, 0.0f), + SecondaryFadeAnimation.DurationOut); } } } @@ -209,7 +236,13 @@ void TitleMenu::UpdateInput() { void TitleMenu::Update(float dt) { UpdateInput(); - + if (CurrentlyFocusedElement) { + static_cast(CurrentlyFocusedElement) + ->HighlightAnimation.Update(dt); + } + if (LastFocusedButton && LastFocusedButton != CurrentlyFocusedElement) { + LastFocusedButton->HighlightAnimation.Update(dt); + } PressToStartAnimation.Update(dt); PrimaryFadeAnimation.Update(dt); SecondaryFadeAnimation.Update(dt); @@ -257,11 +290,6 @@ void TitleMenu::Update(float dt) { << 16; } break; case 3: { // Main Menu Fade In - MainItems->HasFocus = true; - if (CurrentSubMenu) { - CurrentSubMenu->HasFocus = true; - } - MainItems->Tint.a = glm::smoothstep(0.0f, 1.0f, PrimaryFadeAnimation.Progress); ContinueItems->Tint.a = @@ -280,8 +308,12 @@ void TitleMenu::Update(float dt) { if (PrimaryFadeAnimation.IsOut()) { PrimaryFadeAnimation.StartIn(); } - if (CurrentSubMenu && SecondaryFadeAnimation.IsOut()) { - SecondaryFadeAnimation.StartIn(); + + if (CurrentSubMenu) { + if (SlideItemsAnimation.IsIn() && SecondaryFadeAnimation.IsIn()) + CurrentSubMenu->HasFocus = true; + } else if (PrimaryFadeAnimation.IsIn() && SlideItemsAnimation.IsIn()) { + MainItems->HasFocus = true; } if (CurrentSubMenu && !CurrentSubMenu->IsShown) { @@ -296,8 +328,18 @@ void TitleMenu::Update(float dt) { MainItems->Show(); MainItems->Tint.a = 0.0f; CurrentlyFocusedElement = NewGame; + static_cast(CurrentlyFocusedElement) + ->HighlightAnimation.StartIn(true); NewGame->HasFocus = true; } + + if (SecondaryFadeAnimation.IsOut() && CurrentSubMenu) { + if (CurrentSubMenu == ContinueItems) { + HideContinueItems(); + } else if (CurrentSubMenu == ExtraItems) { + HideExtraItems(); + } + } } break; case 4: { } break; @@ -335,6 +377,7 @@ void TitleMenu::Update(float dt) { SlideItemsAnimation.StartIn(); PrimaryFadeAnimation.StartIn(); SecondaryFadeAnimation.StartIn(); + AllowsScriptInput = false; MainItems->Move({Profile::DesignWidth / 2, 0.0f}, SlideItemsAnimation.DurationIn); CurrentSubMenu->Move({Profile::DesignWidth / 2, 0.0f}, @@ -471,16 +514,17 @@ void TitleMenu::ShowContinueItems() { Extra->Move(glm::vec2(0.0f, ItemPadding)); Config->Move(glm::vec2(0.0f, ItemPadding)); Help->Move(glm::vec2(0.0f, ItemPadding)); + ContinueItems->Move(glm::vec2(Profile::DesignWidth / 4, 0.0f), + SecondaryFadeAnimation.DurationOut); } void TitleMenu::HideContinueItems() { ContinueItems->Hide(); MainItems->HasFocus = true; CurrentlyFocusedElement = Continue; - CurrentSubMenu = 0; ContinueItems->HasFocus = true; - SecondaryFadeAnimation.StartOut(); - + CurrentSubMenu = nullptr; + AllowsScriptInput = true; Extra->Move(glm::vec2(0.0f, -ItemPadding)); Config->Move(glm::vec2(0.0f, -ItemPadding)); Help->Move(glm::vec2(0.0f, -ItemPadding)); @@ -497,16 +541,17 @@ void TitleMenu::ShowExtraItems() { Config->Move(glm::vec2(0, ItemPadding)); Help->Move(glm::vec2(0, ItemPadding)); + ExtraItems->Move({Profile::DesignWidth / 4, 0.0f}, + SecondaryFadeAnimation.DurationIn); } void TitleMenu::HideExtraItems() { ExtraItems->Hide(); MainItems->HasFocus = true; CurrentlyFocusedElement = Extra; - CurrentSubMenu = 0; - ExtraItems->HasFocus = true; - SecondaryFadeAnimation.StartOut(); - + CurrentlyFocusedElement->HasFocus = true; + CurrentSubMenu = nullptr; + AllowsScriptInput = true; Config->Move(glm::vec2(0, -ItemPadding)); Help->Move(glm::vec2(0, -ItemPadding)); } diff --git a/src/games/cclcc/titlemenu.h b/src/games/cclcc/titlemenu.h index f653d1b6..96e31409 100644 --- a/src/games/cclcc/titlemenu.h +++ b/src/games/cclcc/titlemenu.h @@ -47,6 +47,9 @@ class TitleMenu : public Menu { Widgets::Group* ContinueItems; Widgets::CCLCC::TitleButton* Load; Widgets::CCLCC::TitleButton* QuickLoad; + + Widgets::CCLCC::TitleButton* LastFocusedButton = nullptr; + void ShowContinueItems(); void HideContinueItems(); diff --git a/src/ui/widgets/cclcc/titlebutton.cpp b/src/ui/widgets/cclcc/titlebutton.cpp index 4f5f96f6..3c0acbd1 100644 --- a/src/ui/widgets/cclcc/titlebutton.cpp +++ b/src/ui/widgets/cclcc/titlebutton.cpp @@ -10,16 +10,29 @@ namespace CCLCC { using namespace Impacto::Profile::CCLCC::TitleMenu; +void TitleButton::UpdateInput() { + if (IsSubButton || HighlightAnimation.State == AS_Stopped) { + Button::UpdateInput(); + } +} + void TitleButton::Render() { - if (HasFocus) { + if (HasFocus || HighlightAnimation.State == AS_Playing) { if (!IsSubButton) { // Main buttons - Renderer->DrawSprite(HighlightSprite, + Sprite newHighlightSprite = HighlightSprite; + float smoothProgress = + HighlightAnimation.State == AS_Playing + ? glm::smoothstep(0.0f, 1.0f, HighlightAnimation.Progress) + : 1.0f; + newHighlightSprite.Bounds.Width *= smoothProgress; + Renderer->DrawSprite(newHighlightSprite, glm::vec2(Bounds.X - ItemHighlightOffsetX, Bounds.Y - ItemHighlightOffsetY), Tint); + glm::vec4 pointerTint = glm::vec4(1.0f, 1.0f, 1.0f, smoothProgress); Renderer->DrawSprite( ItemHighlightPointerSprite, - glm::vec2(Bounds.X - ItemHighlightPointerY, Bounds.Y), Tint); + glm::vec2(Bounds.X - ItemHighlightPointerY, Bounds.Y), pointerTint); Renderer->DrawSprite(FocusedSprite, glm::vec2(Bounds.X, Bounds.Y), Tint); } else { // Sub buttons Renderer->DrawSprite(HighlightSprite, glm::vec2(Bounds.X, Bounds.Y), diff --git a/src/ui/widgets/cclcc/titlebutton.h b/src/ui/widgets/cclcc/titlebutton.h index 291c79d2..fa42822d 100644 --- a/src/ui/widgets/cclcc/titlebutton.h +++ b/src/ui/widgets/cclcc/titlebutton.h @@ -11,9 +11,14 @@ class TitleButton : public Widgets::Button { public: TitleButton(int id, Sprite const& norm, Sprite const& focused, Sprite const& highlight, glm::vec2 pos) - : Widgets::Button(id, norm, focused, highlight, pos) {} + : Widgets::Button(id, norm, focused, highlight, pos) { + HighlightAnimation.DurationIn = 0.3f; + HighlightAnimation.DurationOut = 0.3f; + } void Render() override; + void UpdateInput() override; bool IsSubButton = false; + Animation HighlightAnimation; }; } // namespace CCLCC