diff --git a/CMakeLists.txt b/CMakeLists.txt index a8763803..aa4aef40 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -243,6 +243,7 @@ set(Impacto_Src src/ui/widgets/cc/backlogentry.cpp src/ui/widgets/cc/titlebutton.cpp src/ui/widgets/cclcc/titlebutton.cpp + src/ui/widgets/cclcc/optionsbinarybutton.cpp src/ui/widgets/cclcc/saveentrybutton.cpp src/ui/widgets/cclcc/sysmenubutton.cpp src/ui/widgets/cclcc/tipsentrybutton.cpp @@ -554,6 +555,7 @@ set(Impacto_Header src/ui/widgets/cc/backlogentry.h src/ui/widgets/cc/titlebutton.h src/ui/widgets/cclcc/titlebutton.h + src/ui/widgets/cclcc/optionsbinarybutton.h src/renderer/3d/camera.h src/renderer/3d/model.h diff --git a/src/games/cclcc/optionsmenu.cpp b/src/games/cclcc/optionsmenu.cpp index 99e13965..7388db6e 100644 --- a/src/games/cclcc/optionsmenu.cpp +++ b/src/games/cclcc/optionsmenu.cpp @@ -2,14 +2,9 @@ #include "../../profile/ui/optionsmenu.h" #include "../../profile/games/cclcc/optionsmenu.h" -#include "../../renderer/renderer.h" -#include "../../mem.h" -#include "../../profile/scriptvars.h" -#include "../../inputsystem.h" +#include "../../profile/scriptinput.h" #include "../../vm/interface/input.h" -#include "../../ui/widgets/button.h" -#include "../../vm/vm.h" -#include "../../audio/audiochannel.h" +#include "../../ui/widgets/cclcc/optionsbinarybutton.h" namespace Impacto { namespace UI { @@ -18,6 +13,8 @@ namespace CCLCC { using namespace Impacto::Profile::OptionsMenu; using namespace Impacto::Profile::CCLCC::OptionsMenu; using namespace Impacto::Profile::ScriptVars; +using namespace Impacto::UI::Widgets; +using namespace Impacto::UI::Widgets::CCLCC; using namespace Impacto::Vm::Interface; OptionsMenu::OptionsMenu() { @@ -27,6 +24,56 @@ OptionsMenu::OptionsMenu() { FadeAnimation.DurationOut = FadeOutDuration; PoleAnimation = Profile::CCLCC::OptionsMenu::PoleAnimation.Instantiate(); + + Pages.reserve(4); + + BasicPage = new Group(this); + BasicPage->FocusLock = false; + for (int i = 0; i < 4; i++) { + glm::vec2 pos = EntriesStartPosition; + pos.y += EntriesVerticalOffset * i; + + BasicPage->Add(new OptionsBinaryButton(BinaryBoxSprite, OnSprite, OffSprite, + LabelSprites[i], pos), + FDIR_DOWN); + } + Pages.push_back(BasicPage); + + TextPage = new Group(this); + TextPage->FocusLock = false; + for (int i = 4; i < 7; i++) { + glm::vec2 pos = EntriesStartPosition; + pos.y += EntriesVerticalOffset * (i - 4); + + TextPage->Add(new OptionsBinaryButton(BinaryBoxSprite, YesSprite, NoSprite, + LabelSprites[i], pos), + FDIR_DOWN); + } + Pages.push_back(TextPage); + + SoundPage = new Group(this); + SoundPage->FocusLock = false; + for (int i = 7; i < 15; i++) { + glm::vec2 pos = SoundEntriesStartPosition; + pos.y += SoundEntriesVerticalOffset * (i - 7); + + SoundPage->Add(new OptionsBinaryButton(BinaryBoxSprite, YesSprite, NoSprite, + LabelSprites[i], pos), + FDIR_DOWN); + } + Pages.push_back(SoundPage); + + VoicePage = new Group(this); + VoicePage->FocusLock = false; + for (int i = 0; i < 12; i++) { + glm::vec2 pos = VoicePosition; + pos += VoiceEntriesOffset * glm::vec2(i % 3, i / 3); + + VoicePage->Add(new Label(NametagSprites[i], pos), FDIR_RIGHT); + } + Pages.push_back(VoicePage); + + CurrentPage = 0; } void OptionsMenu::Show() { @@ -34,25 +81,32 @@ void OptionsMenu::Show() { State = Showing; FadeAnimation.StartIn(); PoleAnimation.StartIn(); - // FirstPage->Show(); - if (UI::FocusedMenu != 0) { + + Pages.at(CurrentPage)->Show(); + + if (UI::FocusedMenu != nullptr) { LastFocusedMenu = UI::FocusedMenu; LastFocusedMenu->IsFocused = false; } IsFocused = true; UI::FocusedMenu = this; + + CurrentlyFocusedElement = Pages.at(CurrentPage)->GetFirstFocusableChild(); + CurrentlyFocusedElement->HasFocus = true; } } + void OptionsMenu::Hide() { if (State != Hidden) { State = Hiding; FadeAnimation.StartOut(); PoleAnimation.StartOut(); - if (LastFocusedMenu != 0) { + + if (LastFocusedMenu != nullptr) { UI::FocusedMenu = LastFocusedMenu; LastFocusedMenu->IsFocused = true; } else { - UI::FocusedMenu = 0; + UI::FocusedMenu = nullptr; } IsFocused = false; } @@ -70,6 +124,10 @@ void OptionsMenu::Update(float dt) { ScrWork[SW_SYSSUBMENUNO] == 5) { Show(); } + + int newPageOffset = -(int)(bool)(PADinputButtonWentDown & PAD1L1) + + (int)(bool)(PADinputButtonWentDown & PAD1R1); + GoToPage((CurrentPage + newPageOffset) % Pages.size()); } void OptionsMenu::Render() { @@ -80,7 +138,10 @@ void OptionsMenu::Render() { Renderer->DrawSprite(BackgroundSprite, BackgroundPosition, col); Renderer->DrawSprite(HeaderSprite, HeaderPosition, col); - Renderer->DrawSprite(PageHeaderSprites[2], PageHeaderPosition, col); + Renderer->DrawSprite(PageHeaderSprites[+CurrentPage], PageHeaderPosition, + col); + Pages.at(CurrentPage)->Render(); + /* for (int i = 7; i < 15; i++) { glm::vec2 pos = SoundEntriesStartPosition; pos.y += SoundEntriesVerticalOffset * (i - 7); @@ -93,12 +154,13 @@ void OptionsMenu::Render() { Renderer->DrawSprite(BinaryBoxSprite, boxPos, col); Renderer->DrawSprite(YesSprite, boxPos, col); Renderer->DrawSprite( - NoSprite, boxPos + glm::vec2(BinaryBoxSprite.ScaledWidth() / 2, 0), - col); + NoSprite, boxPos + glm::vec2(BinaryBoxSprite.ScaledWidth() / 2, 0), + col); } else { Renderer->DrawSprite(SliderTrackSprite, pos + SliderTrackOffset, col); } } + */ Renderer->DrawSprite(PoleAnimation.CurrentSprite(), PagePanelPosition, col); @@ -106,6 +168,21 @@ void OptionsMenu::Render() { } } +void OptionsMenu::GoToPage(int pageNumber) { + if (CurrentPage == pageNumber) return; + + Pages.at(CurrentPage)->HasFocus = false; + + CurrentPage = pageNumber; + Group& page = *Pages.at(CurrentPage); + + page.HasFocus = true; + page.Show(); + + CurrentlyFocusedElement = page.GetFirstFocusableChild(); + CurrentlyFocusedElement->HasFocus = true; +} + } // namespace CCLCC } // namespace UI } // namespace Impacto \ No newline at end of file diff --git a/src/games/cclcc/optionsmenu.h b/src/games/cclcc/optionsmenu.h index f7b888ba..5cfb59f4 100644 --- a/src/games/cclcc/optionsmenu.h +++ b/src/games/cclcc/optionsmenu.h @@ -2,6 +2,7 @@ #include "../../ui/menu.h" #include "../../spriteanimation.h" +#include "../../ui/widgets/group.h" namespace Impacto { namespace UI { @@ -17,8 +18,18 @@ class OptionsMenu : public Menu { void Render(); private: + void GoToPage(int pageNumber); + Animation FadeAnimation; SpriteAnimation PoleAnimation; + + Widgets::Group* BasicPage; + Widgets::Group* TextPage; + Widgets::Group* SoundPage; + Widgets::Group* VoicePage; + + int CurrentPage; + std::vector Pages; }; } // namespace CCLCC diff --git a/src/spritesheet.h b/src/spritesheet.h index b60c2b2a..5f727a1b 100644 --- a/src/spritesheet.h +++ b/src/spritesheet.h @@ -27,8 +27,8 @@ struct Sprite { RectF Bounds{0.0f, 0.0f, 0.0f, 0.0f}; glm::vec2 BaseScale; - float ScaledWidth() { return Bounds.Width * BaseScale.x; } - float ScaledHeight() { return Bounds.Height * BaseScale.y; } + float ScaledWidth() const { return Bounds.Width * BaseScale.x; } + float ScaledHeight() const { return Bounds.Height * BaseScale.y; } void SetScaledWidth(float scaledWidth) { Bounds.Width = scaledWidth / BaseScale.x; } diff --git a/src/ui/widgets/cclcc/optionsbinarybutton.cpp b/src/ui/widgets/cclcc/optionsbinarybutton.cpp new file mode 100644 index 00000000..7ef5beae --- /dev/null +++ b/src/ui/widgets/cclcc/optionsbinarybutton.cpp @@ -0,0 +1,69 @@ +#include "optionsbinarybutton.h" + +#include "../../../profile/games/cclcc/optionsmenu.h" +#include "../../../renderer/renderer.h" + +using namespace Impacto::Profile::CCLCC::OptionsMenu; + +namespace Impacto { +namespace UI { +namespace Widgets { +namespace CCLCC { + +OptionsBinaryButton::OptionsBinaryButton(const Sprite& box, + const Sprite& trueLabel, + const Sprite& falseLabel, + const Sprite& label, glm::vec2 pos) + : BoxSprite(box), + TrueSprite(trueLabel), + FalseSprite(falseLabel), + LabelSprite(label) { + Bounds = RectF(pos.x, pos.y, BinaryBoxOffset.x + BoxSprite.ScaledWidth(), + LabelSprite.ScaledHeight()); +} + +inline glm::vec2 OptionsBinaryButton::GetTruePos() const { + return Bounds.GetPos() + BinaryBoxOffset; +} + +inline glm::vec2 OptionsBinaryButton::GetFalsePos() const { + return Bounds.GetPos() + BinaryBoxOffset + + glm::vec2(BoxSprite.ScaledWidth() / 2, 0.0f); +} + +void OptionsBinaryButton::Render() { + HighlightTint.a = Tint.a; + glm::vec4 black = glm::vec4(0.0f, 0.0f, 0.0f, Tint.a); + + glm::vec4 trueTint; + glm::vec4 falseTint; + glm::vec2 highlightPos; + RectF highlightBounds(0.0f, 0.0f, BoxSprite.ScaledWidth() / 2, + BoxSprite.ScaledHeight()); + if (State) { + trueTint = Tint; + falseTint = black; + highlightPos = GetTruePos(); + } else { + trueTint = black; + falseTint = Tint; + highlightPos = GetFalsePos(); + } + highlightBounds.X = highlightPos.x; + highlightBounds.Y = highlightPos.y; + + Renderer->DrawSprite(LabelSprite, Bounds.GetPos(), black); + + Renderer->DrawRect(highlightBounds, HighlightTint); + Renderer->DrawSprite(BoxSprite, GetTruePos(), Tint); + + Renderer->DrawSprite(TrueSprite, GetTruePos(), trueTint); + Renderer->DrawSprite(FalseSprite, GetFalsePos(), falseTint); +} + +void OptionsBinaryButton::UpdateInput() {} + +} // namespace CCLCC +} // namespace Widgets +} // namespace UI +} // namespace Impacto \ No newline at end of file diff --git a/src/ui/widgets/cclcc/optionsbinarybutton.h b/src/ui/widgets/cclcc/optionsbinarybutton.h new file mode 100644 index 00000000..03f0c5dd --- /dev/null +++ b/src/ui/widgets/cclcc/optionsbinarybutton.h @@ -0,0 +1,37 @@ +#pragma once + +#include "../../widget.h" +#include "../../../spritesheet.h" + +namespace Impacto { +namespace UI { +namespace Widgets { +namespace CCLCC { + +class OptionsBinaryButton : public Widget { + public: + OptionsBinaryButton(const Sprite& box, const Sprite& trueLabel, + const Sprite& falseLabel, const Sprite& label, + glm::vec2 pos); + + void Render() override; + void UpdateInput() override; + + private: + inline glm::vec2 GetTruePos() const; + inline glm::vec2 GetFalsePos() const; + + const Sprite& BoxSprite; + const Sprite& TrueSprite; + const Sprite& FalseSprite; + const Sprite& LabelSprite; + + glm::vec4 HighlightTint = glm::vec4(0.94f, 0.49f, 0.59f, 1.0f); + + bool State = true; +}; + +} // namespace CCLCC +} // namespace Widgets +} // namespace UI +} // namespace Impacto \ No newline at end of file diff --git a/src/util.h b/src/util.h index 96ecbeeb..4bc53701 100644 --- a/src/util.h +++ b/src/util.h @@ -80,6 +80,9 @@ struct RectF { return !(*this == other); } + constexpr glm::vec2 GetPos() const { return glm::vec2(X, Y); } + constexpr glm::vec2 GetSize() const { return glm::vec2(Width, Height); } + static RectF Coalesce(const RectF& first, const RectF& second); };