From a0f52411d3e1a1396957455b4837799d4b32fbe0 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Wed, 10 Jan 2024 13:52:48 +0100 Subject: [PATCH] Add tabs to the launcher window --- .../ZWidget/include/zwidget/core/widget.h | 4 + .../src/widgets/tabwidget/tabwidget.cpp | 20 +- src/CMakeLists.txt | 4 + src/launcher/launcherbanner.cpp | 34 ++ src/launcher/launcherbanner.h | 21 ++ src/launcher/launcherbuttonbar.cpp | 46 +++ src/launcher/launcherbuttonbar.h | 25 ++ src/launcher/launcherwindow.cpp | 321 ++---------------- src/launcher/launcherwindow.h | 63 +--- src/launcher/playgamepage.cpp | 100 ++++++ src/launcher/playgamepage.h | 32 ++ src/launcher/settingspage.cpp | 206 +++++++++++ src/launcher/settingspage.h | 47 +++ 13 files changed, 592 insertions(+), 331 deletions(-) create mode 100644 src/launcher/launcherbanner.cpp create mode 100644 src/launcher/launcherbanner.h create mode 100644 src/launcher/launcherbuttonbar.cpp create mode 100644 src/launcher/launcherbuttonbar.h create mode 100644 src/launcher/playgamepage.cpp create mode 100644 src/launcher/playgamepage.h create mode 100644 src/launcher/settingspage.cpp create mode 100644 src/launcher/settingspage.h diff --git a/libraries/ZWidget/include/zwidget/core/widget.h b/libraries/ZWidget/include/zwidget/core/widget.h index 932a6b5dd..639bfe09c 100644 --- a/libraries/ZWidget/include/zwidget/core/widget.h +++ b/libraries/ZWidget/include/zwidget/core/widget.h @@ -39,6 +39,10 @@ public: // Widget noncontent area void SetNoncontentSizes(double left, double top, double right, double bottom); + double GetNoncontentLeft() const { return Noncontent.Left; } + double GetNoncontentTop() const { return Noncontent.Top; } + double GetNoncontentRight() const { return Noncontent.Right; } + double GetNoncontentBottom() const { return Noncontent.Bottom; } // Widget frame box Rect GetFrameGeometry() const; diff --git a/libraries/ZWidget/src/widgets/tabwidget/tabwidget.cpp b/libraries/ZWidget/src/widgets/tabwidget/tabwidget.cpp index adb2e2917..2d8b26ba8 100644 --- a/libraries/ZWidget/src/widgets/tabwidget/tabwidget.cpp +++ b/libraries/ZWidget/src/widgets/tabwidget/tabwidget.cpp @@ -91,6 +91,7 @@ void TabWidget::OnGeometryChanged() TabBar::TabBar(Widget* parent) : Widget(parent) { + SetNoncontentSizes(20.0, 0.0, 20.0, 0.0); } int TabBar::AddTab(const std::string& label) @@ -151,6 +152,9 @@ int TabBar::GetTabIndex(TabBarTab* tab) void TabBar::OnPaintFrame(Canvas* canvas) { + double w = GetFrameGeometry().width; + double h = GetFrameGeometry().height; + canvas->fillRect(Rect::xywh(0.0, 0.0, w, h), Colorf::fromRgba8(38, 38, 38)); } void TabBar::OnGeometryChanged() @@ -160,7 +164,7 @@ void TabBar::OnGeometryChanged() double x = 0.0; for (TabBarTab* tab : Tabs) { - double tabWidth = tab->GetPreferredWidth(); + double tabWidth = tab->GetNoncontentLeft() + tab->GetPreferredWidth() + tab->GetNoncontentRight(); tab->SetFrameGeometry(Rect::xywh(x, 0.0, tabWidth, h)); x += tabWidth; } @@ -170,6 +174,7 @@ void TabBar::OnGeometryChanged() TabBarTab::TabBarTab(Widget* parent) : Widget(parent) { + SetNoncontentSizes(15.0, 0.0, 15.0, 0.0); } void TabBarTab::SetText(const std::string& text) @@ -228,6 +233,16 @@ double TabBarTab::GetPreferredWidth() const void TabBarTab::OnPaintFrame(Canvas* canvas) { + double w = GetFrameGeometry().width; + double h = GetFrameGeometry().height; + if (IsCurrent) + { + canvas->fillRect(Rect::xywh(0.0, 0.0, w, h), Colorf::fromRgba8(51, 51, 51)); + } + else if (hot) + { + canvas->fillRect(Rect::xywh(0.0, 0.0, w, h), Colorf::fromRgba8(45, 45, 45)); + } } void TabBarTab::OnGeometryChanged() @@ -242,7 +257,7 @@ void TabBarTab::OnGeometryChanged() } if (Label) { - Label->SetFrameGeometry(Rect::xywh(x, 0.0, std::max(w - x, 0.0), h)); + Label->SetFrameGeometry(Rect::xywh(x, (h - Label->GetPreferredHeight()) * 0.5, std::max(w - x, 0.0), Label->GetPreferredHeight())); } } @@ -283,6 +298,7 @@ void TabBarTab::OnMouseLeave() TabWidgetStack::TabWidgetStack(Widget* parent) : Widget(parent) { + SetNoncontentSizes(20.0, 5.0, 20.0, 5.0); } void TabWidgetStack::SetCurrentWidget(Widget* widget) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index afc3686b8..58dbefd6f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -978,6 +978,10 @@ set (PCH_SOURCES rendering/swrenderer/textures/swcanvastexture.cpp events.cpp launcher/launcherwindow.cpp + launcher/launcherbanner.cpp + launcher/launcherbuttonbar.cpp + launcher/playgamepage.cpp + launcher/settingspage.cpp common/audio/sound/i_sound.cpp common/audio/sound/oalsound.cpp diff --git a/src/launcher/launcherbanner.cpp b/src/launcher/launcherbanner.cpp new file mode 100644 index 000000000..69f7e7ee1 --- /dev/null +++ b/src/launcher/launcherbanner.cpp @@ -0,0 +1,34 @@ + +#include "launcherbanner.h" +#include "gstrings.h" +#include "version.h" +#include +#include +#include + +LauncherBanner::LauncherBanner(Widget* parent) : Widget(parent) +{ + Logo = new ImageBox(this); + VersionLabel = new TextLabel(this); + VersionLabel->SetTextAlignment(TextLabelAlignment::Right); + + Logo->SetImage(Image::LoadResource("widgets/banner.png")); +} + +void LauncherBanner::UpdateLanguage() +{ + FString versionText = GStrings("PICKER_VERSION"); + versionText.Substitute("%s", GetVersionString()); + VersionLabel->SetText(versionText.GetChars()); +} + +double LauncherBanner::GetPreferredHeight() const +{ + return Logo->GetPreferredHeight(); +} + +void LauncherBanner::OnGeometryChanged() +{ + Logo->SetFrameGeometry(0.0, 0.0, GetWidth(), Logo->GetPreferredHeight()); + VersionLabel->SetFrameGeometry(20.0, GetHeight() - 10.0 - VersionLabel->GetPreferredHeight(), GetWidth() - 40.0, VersionLabel->GetPreferredHeight()); +} diff --git a/src/launcher/launcherbanner.h b/src/launcher/launcherbanner.h new file mode 100644 index 000000000..9a27a5694 --- /dev/null +++ b/src/launcher/launcherbanner.h @@ -0,0 +1,21 @@ +#pragma once + +#include + +class ImageBox; +class TextLabel; + +class LauncherBanner : public Widget +{ +public: + LauncherBanner(Widget* parent); + void UpdateLanguage(); + + double GetPreferredHeight() const; + +private: + void OnGeometryChanged() override; + + ImageBox* Logo = nullptr; + TextLabel* VersionLabel = nullptr; +}; diff --git a/src/launcher/launcherbuttonbar.cpp b/src/launcher/launcherbuttonbar.cpp new file mode 100644 index 000000000..d542ea51e --- /dev/null +++ b/src/launcher/launcherbuttonbar.cpp @@ -0,0 +1,46 @@ + +#include "launcherbuttonbar.h" +#include "launcherwindow.h" +#include "gstrings.h" +#include + +LauncherButtonbar::LauncherButtonbar(LauncherWindow* parent) : Widget(parent) +{ + PlayButton = new PushButton(this); + ExitButton = new PushButton(this); + + PlayButton->OnClick = [=]() { OnPlayButtonClicked(); }; + ExitButton->OnClick = [=]() { OnExitButtonClicked(); }; +} + +void LauncherButtonbar::UpdateLanguage() +{ + PlayButton->SetText(GStrings("PICKER_PLAY")); + ExitButton->SetText(GStrings("PICKER_EXIT")); +} + +double LauncherButtonbar::GetPreferredHeight() const +{ + return 20.0 + std::max(PlayButton->GetPreferredHeight(), ExitButton->GetPreferredHeight()); +} + +void LauncherButtonbar::OnGeometryChanged() +{ + PlayButton->SetFrameGeometry(20.0, 10.0, 120.0, PlayButton->GetPreferredHeight()); + ExitButton->SetFrameGeometry(GetWidth() - 20.0 - 120.0, 10.0, 120.0, PlayButton->GetPreferredHeight()); +} + +void LauncherButtonbar::OnPlayButtonClicked() +{ + GetLauncher()->Start(); +} + +void LauncherButtonbar::OnExitButtonClicked() +{ + GetLauncher()->Exit(); +} + +LauncherWindow* LauncherButtonbar::GetLauncher() const +{ + return static_cast(Parent()); +} diff --git a/src/launcher/launcherbuttonbar.h b/src/launcher/launcherbuttonbar.h new file mode 100644 index 000000000..4872cb612 --- /dev/null +++ b/src/launcher/launcherbuttonbar.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +class LauncherWindow; +class PushButton; + +class LauncherButtonbar : public Widget +{ +public: + LauncherButtonbar(LauncherWindow* parent); + void UpdateLanguage(); + + double GetPreferredHeight() const; + +private: + void OnGeometryChanged() override; + void OnPlayButtonClicked(); + void OnExitButtonClicked(); + + LauncherWindow* GetLauncher() const; + + PushButton* PlayButton = nullptr; + PushButton* ExitButton = nullptr; +}; diff --git a/src/launcher/launcherwindow.cpp b/src/launcher/launcherwindow.cpp index 48d1e5b7d..ae0551ad9 100644 --- a/src/launcher/launcherwindow.cpp +++ b/src/launcher/launcherwindow.cpp @@ -1,25 +1,15 @@ #include "launcherwindow.h" +#include "launcherbanner.h" +#include "launcherbuttonbar.h" +#include "playgamepage.h" +#include "settingspage.h" #include "v_video.h" #include "version.h" #include "i_interface.h" #include "gstrings.h" #include -#include #include -#include -#include -#include -#include -#include -#include -#include - -#ifdef RENDER_BACKENDS -EXTERN_CVAR(Int, vid_preferbackend); -#endif - -EXTERN_CVAR(String, language) -EXTERN_CVAR(Bool, queryiwad); +#include int LauncherWindow::ExecModal(WadStuff* wads, int numwads, int defaultiwad, int* autoloadflags) { @@ -36,39 +26,7 @@ int LauncherWindow::ExecModal(WadStuff* wads, int numwads, int defaultiwad, int* return launcher->ExecResult; } -void LauncherWindow::UpdateLanguage() -{ - LangLabel->SetText(GStrings("OPTMNU_LANGUAGE")); - SelectLabel->SetText(GStrings("PICKER_SELECT")); - PlayButton->SetText(GStrings("PICKER_PLAY")); - ExitButton->SetText(GStrings("PICKER_EXIT")); - - GeneralLabel->SetText(GStrings("PICKER_GENERAL")); - ExtrasLabel->SetText(GStrings("PICKER_EXTRA")); - FullscreenCheckbox->SetText(GStrings("PICKER_FULLSCREEN")); - DisableAutoloadCheckbox->SetText(GStrings("PICKER_NOAUTOLOAD")); - DontAskAgainCheckbox->SetText(GStrings("PICKER_DONTASK")); - LightsCheckbox->SetText(GStrings("PICKER_LIGHTS")); - BrightmapsCheckbox->SetText(GStrings("PICKER_BRIGHTMAPS")); - WidescreenCheckbox->SetText(GStrings("PICKER_WIDESCREEN")); - ParametersLabel->SetText(GStrings("PICKER_ADDPARM")); - -#ifdef RENDER_BACKENDS - BackendLabel->SetText(GStrings("PICKER_PREFERBACKEND")); - VulkanCheckbox->SetText(GStrings("OPTVAL_VULKAN")); - OpenGLCheckbox->SetText(GStrings("OPTVAL_OPENGL")); - GLESCheckbox->SetText(GStrings("OPTVAL_OPENGLES")); -#endif - - FString welcomeText = GStrings("PICKER_WELCOME"); - welcomeText.Substitute("%s", GAMENAME); - FString versionText = GStrings("PICKER_VERSION"); - versionText.Substitute("%s", GetVersionString()); - WelcomeLabel->SetText(welcomeText.GetChars()); - VersionLabel->SetText(versionText.GetChars()); -} - -LauncherWindow::LauncherWindow(WadStuff* wads, int numwads, int defaultiwad, int* autoloadflags) : Widget(nullptr, WidgetType::Window), AutoloadFlags(autoloadflags) +LauncherWindow::LauncherWindow(WadStuff* wads, int numwads, int defaultiwad, int* autoloadflags) : Widget(nullptr, WidgetType::Window) { SetWindowBackground(Colorf::fromRgba8(51, 51, 51)); SetWindowBorderColor(Colorf::fromRgba8(51, 51, 51)); @@ -76,270 +34,65 @@ LauncherWindow::LauncherWindow(WadStuff* wads, int numwads, int defaultiwad, int SetWindowCaptionTextColor(Colorf::fromRgba8(226, 223, 219)); SetWindowTitle(GAMENAME); - Logo = new ImageBox(this); - WelcomeLabel = new TextLabel(this); - VersionLabel = new TextLabel(this); - LangLabel = new TextLabel(this); - SelectLabel = new TextLabel(this); - GeneralLabel = new TextLabel(this); - ExtrasLabel = new TextLabel(this); - ParametersLabel = new TextLabel(this); - FullscreenCheckbox = new CheckboxLabel(this); - DisableAutoloadCheckbox = new CheckboxLabel(this); - DontAskAgainCheckbox = new CheckboxLabel(this); - LightsCheckbox = new CheckboxLabel(this); - BrightmapsCheckbox = new CheckboxLabel(this); - WidescreenCheckbox = new CheckboxLabel(this); - PlayButton = new PushButton(this); - ExitButton = new PushButton(this); - LangList = new ListView(this); - GamesList = new ListView(this); - ParametersEdit = new LineEdit(this); + Banner = new LauncherBanner(this); + Pages = new TabWidget(this); + Buttonbar = new LauncherButtonbar(this); -#ifdef RENDER_BACKENDS - BackendLabel = new TextLabel(this); - VulkanCheckbox = new CheckboxLabel(this); - OpenGLCheckbox = new CheckboxLabel(this); - GLESCheckbox = new CheckboxLabel(this); -#endif + PlayGame = new PlayGamePage(this, wads, numwads, defaultiwad); + Settings = new SettingsPage(this, autoloadflags); - PlayButton->OnClick = [=]() { OnPlayButtonClicked(); }; - ExitButton->OnClick = [=]() { OnExitButtonClicked(); }; - GamesList->OnActivated = [=]() { OnGamesListActivated(); }; + Pages->AddTab(PlayGame, "Play"); + Pages->AddTab(Settings, "Settings"); UpdateLanguage(); - FullscreenCheckbox->SetChecked(vid_fullscreen); - DontAskAgainCheckbox->SetChecked(!queryiwad); - - int flags = *autoloadflags; - DisableAutoloadCheckbox->SetChecked(flags & 1); - LightsCheckbox->SetChecked(flags & 2); - BrightmapsCheckbox->SetChecked(flags & 4); - WidescreenCheckbox->SetChecked(flags & 8); - -#ifdef RENDER_BACKENDS - OpenGLCheckbox->SetRadioStyle(true); - VulkanCheckbox->SetRadioStyle(true); - GLESCheckbox->SetRadioStyle(true); - OpenGLCheckbox->FuncChanged = [this](bool on) { if (on) { VulkanCheckbox->SetChecked(false); GLESCheckbox->SetChecked(false); }}; - VulkanCheckbox->FuncChanged = [this](bool on) { if (on) { OpenGLCheckbox->SetChecked(false); GLESCheckbox->SetChecked(false); }}; - GLESCheckbox->FuncChanged = [this](bool on) { if (on) { VulkanCheckbox->SetChecked(false); OpenGLCheckbox->SetChecked(false); }}; - switch (vid_preferbackend) - { - case 0: - OpenGLCheckbox->SetChecked(true); - break; - case 1: - VulkanCheckbox->SetChecked(true); - break; - case 2: - GLESCheckbox->SetChecked(true); - break; - } -#endif - - - try - { - auto data = LoadWidgetData("menudef.txt"); - FScanner sc; - sc.OpenMem("menudef.txt", data); - while (sc.GetString()) - { - if (sc.Compare("OptionString")) - { - sc.MustGetString(); - if (sc.Compare("LanguageOptions")) - { - sc.MustGetStringName("{"); - while (!sc.CheckString("}")) - { - sc.MustGetString(); - FString iso = sc.String; - sc.MustGetStringName(","); - sc.MustGetString(); - if(iso.CompareNoCase("auto")) - languages.push_back(std::make_pair(iso, FString(sc.String))); - } - } - } - } - } - catch (const std::exception& ex) - { - hideLanguage = true; - } - int i = 0; - for (auto& l : languages) - { - LangList->AddItem(l.second.GetChars()); - if (!l.first.CompareNoCase(::language)) - LangList->SetSelectedItem(i); - i++; - } - for (int i = 0; i < numwads; i++) - { - const char* filepart = strrchr(wads[i].Path.GetChars(), '/'); - if (filepart == NULL) - filepart = wads[i].Path.GetChars(); - else - filepart++; - - FString work; - if (*filepart) work.Format("%s (%s)", wads[i].Name.GetChars(), filepart); - else work = wads[i].Name.GetChars(); - - GamesList->AddItem(work.GetChars()); - } - - if (defaultiwad >= 0 && defaultiwad < numwads) - { - GamesList->SetSelectedItem(defaultiwad); - GamesList->ScrollToItem(defaultiwad); - } - - Logo->SetImage(Image::LoadResource("widgets/banner.png")); - - GamesList->SetFocus(); - - LangList->OnChanged = [this](int i) - { - ::language = languages[i].first.GetChars(); - GStrings.UpdateLanguage(::language); // CVAR callbacks are not active yet. - UpdateLanguage(); - Update(); - }; + Pages->SetCurrentWidget(PlayGame); + PlayGame->SetFocus(); } -void LauncherWindow::OnClose() +void LauncherWindow::Start() { - OnExitButtonClicked(); -} + Settings->Save(); -void LauncherWindow::OnPlayButtonClicked() -{ - vid_fullscreen = FullscreenCheckbox->GetChecked(); - queryiwad = !DontAskAgainCheckbox->GetChecked(); - - int flags = 0; - if (DisableAutoloadCheckbox->GetChecked()) flags |= 1; - if (LightsCheckbox->GetChecked()) flags |= 2; - if (BrightmapsCheckbox->GetChecked()) flags |= 4; - if (WidescreenCheckbox->GetChecked()) flags |= 8; - *AutoloadFlags = flags; - -#ifdef RENDER_BACKENDS - int v = 1; - if (OpenGLCheckbox->GetChecked()) v = 0; - else if (VulkanCheckbox->GetChecked()) v = 1; - else if (GLESCheckbox->GetChecked()) v = 2; - if (v != vid_preferbackend) vid_preferbackend = v; -#endif - - std::string extraargs = ParametersEdit->GetText(); + std::string extraargs = PlayGame->GetExtraArgs(); if (!extraargs.empty()) { // To do: restart the process like the cocoa backend is doing? } - ExecResult = GamesList->GetSelectedItem(); + ExecResult = PlayGame->GetSelectedGame(); DisplayWindow::ExitLoop(); } -void LauncherWindow::OnExitButtonClicked() +void LauncherWindow::Exit() { ExecResult = -1; DisplayWindow::ExitLoop(); } -void LauncherWindow::OnGamesListActivated() +void LauncherWindow::UpdateLanguage() { - OnPlayButtonClicked(); + Banner->UpdateLanguage(); + PlayGame->UpdateLanguage(); + Settings->UpdateLanguage(); + Buttonbar->UpdateLanguage(); +} + +void LauncherWindow::OnClose() +{ + Exit(); } void LauncherWindow::OnGeometryChanged() { - double y = 0.0; + double top = 0.0; + double bottom = GetHeight(); - Logo->SetFrameGeometry(0.0, y, GetWidth(), Logo->GetPreferredHeight()); - y += Logo->GetPreferredHeight(); + Banner->SetFrameGeometry(0.0, top, GetWidth(), Banner->GetPreferredHeight()); + top += Banner->GetPreferredHeight(); - y += 10.0; + bottom -= Buttonbar->GetPreferredHeight(); + Buttonbar->SetFrameGeometry(0.0, bottom, GetWidth(), Buttonbar->GetPreferredHeight()); - WelcomeLabel->SetFrameGeometry(20.0, y, GetWidth() - 40.0, WelcomeLabel->GetPreferredHeight()); - y += WelcomeLabel->GetPreferredHeight(); - - VersionLabel->SetFrameGeometry(20.0, y, GetWidth() - 40.0, VersionLabel->GetPreferredHeight()); - y += VersionLabel->GetPreferredHeight(); - - y += 10.0; - - if (!hideLanguage) - { - LangLabel->SetFrameGeometry(20.0, y, GetWidth() - 40.0, SelectLabel->GetPreferredHeight()); - y += LangLabel->GetPreferredHeight(); - LangList->SetFrameGeometry(20.0, y, GetWidth() - 40.0, 61); - y += 64.0; - } - - - SelectLabel->SetFrameGeometry(20.0, y, GetWidth() - 40.0, SelectLabel->GetPreferredHeight()); - y += SelectLabel->GetPreferredHeight(); - - double listViewTop = y; - - y = GetHeight() - 15.0 - PlayButton->GetPreferredHeight(); - PlayButton->SetFrameGeometry(20.0, y, 120.0, PlayButton->GetPreferredHeight()); - ExitButton->SetFrameGeometry(GetWidth() - 20.0 - 120.0, y, 120.0, PlayButton->GetPreferredHeight()); - - y -= 20.0; - - double editHeight = 24.0; - y -= editHeight; - ParametersEdit->SetFrameGeometry(20.0, y, GetWidth() - 40.0, editHeight); - y -= 5.0; - - double labelHeight = ParametersLabel->GetPreferredHeight(); - y -= labelHeight; - ParametersLabel->SetFrameGeometry(20.0, y, GetWidth() - 40.0, labelHeight); - y -= 10.0; - - double panelWidth = 150.0; - -#ifdef RENDER_BACKENDS - auto yy = y; - y -= GLESCheckbox->GetPreferredHeight(); - double x = GetWidth() / 2 - panelWidth / 2; - GLESCheckbox->SetFrameGeometry(x, y, 190.0, GLESCheckbox->GetPreferredHeight()); - - y -= OpenGLCheckbox->GetPreferredHeight(); - OpenGLCheckbox->SetFrameGeometry(x, y, 190.0, OpenGLCheckbox->GetPreferredHeight()); - - y -= VulkanCheckbox->GetPreferredHeight(); - VulkanCheckbox->SetFrameGeometry(x, y, 190.0, VulkanCheckbox->GetPreferredHeight()); - - y -= BackendLabel->GetPreferredHeight(); - BackendLabel->SetFrameGeometry(x, y, 190.0, BackendLabel->GetPreferredHeight()); - - y = yy; -#endif - y -= DontAskAgainCheckbox->GetPreferredHeight(); - DontAskAgainCheckbox->SetFrameGeometry(20.0, y, 190.0, DontAskAgainCheckbox->GetPreferredHeight()); - WidescreenCheckbox->SetFrameGeometry(GetWidth() - 20.0 - panelWidth, y, panelWidth, WidescreenCheckbox->GetPreferredHeight()); - - y -= DisableAutoloadCheckbox->GetPreferredHeight(); - DisableAutoloadCheckbox->SetFrameGeometry(20.0, y, 190.0, DisableAutoloadCheckbox->GetPreferredHeight()); - BrightmapsCheckbox->SetFrameGeometry(GetWidth() - 20.0 - panelWidth, y, panelWidth, BrightmapsCheckbox->GetPreferredHeight()); - - y -= FullscreenCheckbox->GetPreferredHeight(); - FullscreenCheckbox->SetFrameGeometry(20.0, y, 190.0, FullscreenCheckbox->GetPreferredHeight()); - LightsCheckbox->SetFrameGeometry(GetWidth() - 20.0 - panelWidth, y, panelWidth, LightsCheckbox->GetPreferredHeight()); - - y -= GeneralLabel->GetPreferredHeight(); - GeneralLabel->SetFrameGeometry(20.0, y, 190.0, GeneralLabel->GetPreferredHeight()); - ExtrasLabel->SetFrameGeometry(GetWidth() - 20.0 - panelWidth, y, panelWidth, ExtrasLabel->GetPreferredHeight()); - - double listViewBottom = y - 10.0; - GamesList->SetFrameGeometry(20.0, listViewTop, GetWidth() - 40.0, std::max(listViewBottom - listViewTop, 0.0)); + Pages->SetFrameGeometry(0.0, top, GetWidth(), std::max(bottom - top, 0.0)); } diff --git a/src/launcher/launcherwindow.h b/src/launcher/launcherwindow.h index d54f77464..8cdbc6ce7 100644 --- a/src/launcher/launcherwindow.h +++ b/src/launcher/launcherwindow.h @@ -4,15 +4,11 @@ #include "tarray.h" #include "zstring.h" - -#define RENDER_BACKENDS - -class ImageBox; -class TextLabel; -class CheckboxLabel; -class PushButton; -class ListView; -class LineEdit; +class TabWidget; +class LauncherBanner; +class LauncherButtonbar; +class PlayGamePage; +class SettingsPage; struct WadStuff; class LauncherWindow : public Widget @@ -21,44 +17,21 @@ public: static int ExecModal(WadStuff* wads, int numwads, int defaultiwad, int* autoloadflags); LauncherWindow(WadStuff* wads, int numwads, int defaultiwad, int* autoloadflags); - -private: - void OnPlayButtonClicked(); - void OnExitButtonClicked(); - void OnGamesListActivated(); - - void OnClose() override; - void OnGeometryChanged() override; void UpdateLanguage(); - ImageBox* Logo = nullptr; - TextLabel* WelcomeLabel = nullptr; - TextLabel* VersionLabel = nullptr; - TextLabel* LangLabel = nullptr; - TextLabel* SelectLabel = nullptr; - TextLabel* GeneralLabel = nullptr; - TextLabel* ExtrasLabel = nullptr; - TextLabel* ParametersLabel = nullptr; - CheckboxLabel* FullscreenCheckbox = nullptr; - CheckboxLabel* DisableAutoloadCheckbox = nullptr; - CheckboxLabel* DontAskAgainCheckbox = nullptr; - CheckboxLabel* LightsCheckbox = nullptr; - CheckboxLabel* BrightmapsCheckbox = nullptr; - CheckboxLabel* WidescreenCheckbox = nullptr; -#ifdef RENDER_BACKENDS - TextLabel* BackendLabel = nullptr; - CheckboxLabel* VulkanCheckbox = nullptr; - CheckboxLabel* OpenGLCheckbox = nullptr; - CheckboxLabel* GLESCheckbox = nullptr; -#endif - PushButton* PlayButton = nullptr; - PushButton* ExitButton = nullptr; - ListView* GamesList = nullptr; - ListView* LangList = nullptr; - LineEdit* ParametersEdit = nullptr; + void Start(); + void Exit(); + +private: + void OnClose() override; + void OnGeometryChanged() override; + + LauncherBanner* Banner = nullptr; + TabWidget* Pages = nullptr; + LauncherButtonbar* Buttonbar = nullptr; + + PlayGamePage* PlayGame = nullptr; + SettingsPage* Settings = nullptr; - int* AutoloadFlags = nullptr; int ExecResult = -1; - bool hideLanguage = false; - TArray> languages; }; diff --git a/src/launcher/playgamepage.cpp b/src/launcher/playgamepage.cpp new file mode 100644 index 000000000..5c585c9e5 --- /dev/null +++ b/src/launcher/playgamepage.cpp @@ -0,0 +1,100 @@ + +#include "playgamepage.h" +#include "launcherwindow.h" +#include "i_interface.h" +#include "gstrings.h" +#include "version.h" +#include +#include +#include + +PlayGamePage::PlayGamePage(LauncherWindow* launcher, WadStuff* wads, int numwads, int defaultiwad) : Widget(nullptr), Launcher(launcher) +{ + WelcomeLabel = new TextLabel(this); + SelectLabel = new TextLabel(this); + ParametersLabel = new TextLabel(this); + GamesList = new ListView(this); + ParametersEdit = new LineEdit(this); + + for (int i = 0; i < numwads; i++) + { + const char* filepart = strrchr(wads[i].Path.GetChars(), '/'); + if (filepart == NULL) + filepart = wads[i].Path.GetChars(); + else + filepart++; + + FString work; + if (*filepart) work.Format("%s (%s)", wads[i].Name.GetChars(), filepart); + else work = wads[i].Name.GetChars(); + + GamesList->AddItem(work.GetChars()); + } + + if (defaultiwad >= 0 && defaultiwad < numwads) + { + GamesList->SetSelectedItem(defaultiwad); + GamesList->ScrollToItem(defaultiwad); + } + + GamesList->OnActivated = [=]() { OnGamesListActivated(); }; +} + +std::string PlayGamePage::GetExtraArgs() +{ + return ParametersEdit->GetText(); +} + +int PlayGamePage::GetSelectedGame() +{ + return GamesList->GetSelectedItem(); +} + +void PlayGamePage::UpdateLanguage() +{ + SelectLabel->SetText(GStrings("PICKER_SELECT")); + ParametersLabel->SetText(GStrings("PICKER_ADDPARM")); + FString welcomeText = GStrings("PICKER_WELCOME"); + welcomeText.Substitute("%s", GAMENAME); + WelcomeLabel->SetText(welcomeText.GetChars()); +} + +void PlayGamePage::OnGamesListActivated() +{ + Launcher->Start(); +} + +void PlayGamePage::OnSetFocus() +{ + GamesList->SetFocus(); +} + +void PlayGamePage::OnGeometryChanged() +{ + double y = 10.0; + + WelcomeLabel->SetFrameGeometry(0.0, y, GetWidth(), WelcomeLabel->GetPreferredHeight()); + y += WelcomeLabel->GetPreferredHeight(); + + y += 10.0; + + SelectLabel->SetFrameGeometry(0.0, y, GetWidth(), SelectLabel->GetPreferredHeight()); + y += SelectLabel->GetPreferredHeight(); + + double listViewTop = y; + + y = GetHeight() - 10.0; + + double editHeight = 24.0; + y -= editHeight; + ParametersEdit->SetFrameGeometry(0.0, y, GetWidth(), editHeight); + y -= 5.0; + + double labelHeight = ParametersLabel->GetPreferredHeight(); + y -= labelHeight; + ParametersLabel->SetFrameGeometry(0.0, y, GetWidth(), labelHeight); + y -= 10.0; + + double listViewBottom = y - 10.0; + GamesList->SetFrameGeometry(0.0, listViewTop, GetWidth(), std::max(listViewBottom - listViewTop, 0.0)); +} diff --git a/src/launcher/playgamepage.h b/src/launcher/playgamepage.h new file mode 100644 index 000000000..af0e95bc3 --- /dev/null +++ b/src/launcher/playgamepage.h @@ -0,0 +1,32 @@ +#pragma once + +#include + +class LauncherWindow; +class TextLabel; +class ListView; +class LineEdit; +struct WadStuff; + +class PlayGamePage : public Widget +{ +public: + PlayGamePage(LauncherWindow* launcher, WadStuff* wads, int numwads, int defaultiwad); + void UpdateLanguage(); + + std::string GetExtraArgs(); + int GetSelectedGame(); + +private: + void OnGeometryChanged() override; + void OnSetFocus() override; + void OnGamesListActivated(); + + LauncherWindow* Launcher = nullptr; + + TextLabel* WelcomeLabel = nullptr; + TextLabel* SelectLabel = nullptr; + TextLabel* ParametersLabel = nullptr; + ListView* GamesList = nullptr; + LineEdit* ParametersEdit = nullptr; +}; diff --git a/src/launcher/settingspage.cpp b/src/launcher/settingspage.cpp new file mode 100644 index 000000000..731c29a15 --- /dev/null +++ b/src/launcher/settingspage.cpp @@ -0,0 +1,206 @@ + +#include "settingspage.h" +#include "launcherwindow.h" +#include "gstrings.h" +#include "i_interface.h" +#include "v_video.h" +#include +#include +#include +#include + +#ifdef RENDER_BACKENDS +EXTERN_CVAR(Int, vid_preferbackend); +#endif + +EXTERN_CVAR(String, language) +EXTERN_CVAR(Bool, queryiwad); + +SettingsPage::SettingsPage(LauncherWindow* launcher, int* autoloadflags) : Widget(nullptr), Launcher(launcher), AutoloadFlags(autoloadflags) +{ + LangLabel = new TextLabel(this); + GeneralLabel = new TextLabel(this); + ExtrasLabel = new TextLabel(this); + FullscreenCheckbox = new CheckboxLabel(this); + DisableAutoloadCheckbox = new CheckboxLabel(this); + DontAskAgainCheckbox = new CheckboxLabel(this); + LightsCheckbox = new CheckboxLabel(this); + BrightmapsCheckbox = new CheckboxLabel(this); + WidescreenCheckbox = new CheckboxLabel(this); + +#ifdef RENDER_BACKENDS + BackendLabel = new TextLabel(this); + VulkanCheckbox = new CheckboxLabel(this); + OpenGLCheckbox = new CheckboxLabel(this); + GLESCheckbox = new CheckboxLabel(this); +#endif + + FullscreenCheckbox->SetChecked(vid_fullscreen); + DontAskAgainCheckbox->SetChecked(!queryiwad); + + int flags = *autoloadflags; + DisableAutoloadCheckbox->SetChecked(flags & 1); + LightsCheckbox->SetChecked(flags & 2); + BrightmapsCheckbox->SetChecked(flags & 4); + WidescreenCheckbox->SetChecked(flags & 8); + +#ifdef RENDER_BACKENDS + OpenGLCheckbox->SetRadioStyle(true); + VulkanCheckbox->SetRadioStyle(true); + GLESCheckbox->SetRadioStyle(true); + OpenGLCheckbox->FuncChanged = [this](bool on) { if (on) { VulkanCheckbox->SetChecked(false); GLESCheckbox->SetChecked(false); }}; + VulkanCheckbox->FuncChanged = [this](bool on) { if (on) { OpenGLCheckbox->SetChecked(false); GLESCheckbox->SetChecked(false); }}; + GLESCheckbox->FuncChanged = [this](bool on) { if (on) { VulkanCheckbox->SetChecked(false); OpenGLCheckbox->SetChecked(false); }}; + switch (vid_preferbackend) + { + case 0: + OpenGLCheckbox->SetChecked(true); + break; + case 1: + VulkanCheckbox->SetChecked(true); + break; + case 2: + GLESCheckbox->SetChecked(true); + break; + } +#endif + + LangList = new ListView(this); + + try + { + auto data = LoadWidgetData("menudef.txt"); + FScanner sc; + sc.OpenMem("menudef.txt", data); + while (sc.GetString()) + { + if (sc.Compare("OptionString")) + { + sc.MustGetString(); + if (sc.Compare("LanguageOptions")) + { + sc.MustGetStringName("{"); + while (!sc.CheckString("}")) + { + sc.MustGetString(); + FString iso = sc.String; + sc.MustGetStringName(","); + sc.MustGetString(); + if(iso.CompareNoCase("auto")) + languages.push_back(std::make_pair(iso, FString(sc.String))); + } + } + } + } + } + catch (const std::exception& ex) + { + hideLanguage = true; + } + int i = 0; + for (auto& l : languages) + { + LangList->AddItem(l.second.GetChars()); + if (!l.first.CompareNoCase(::language)) + LangList->SetSelectedItem(i); + i++; + } + + LangList->OnChanged = [=](int i) { OnLanguageChanged(i); }; +} + +void SettingsPage::Save() +{ + vid_fullscreen = FullscreenCheckbox->GetChecked(); + queryiwad = !DontAskAgainCheckbox->GetChecked(); + + int flags = 0; + if (DisableAutoloadCheckbox->GetChecked()) flags |= 1; + if (LightsCheckbox->GetChecked()) flags |= 2; + if (BrightmapsCheckbox->GetChecked()) flags |= 4; + if (WidescreenCheckbox->GetChecked()) flags |= 8; + *AutoloadFlags = flags; + +#ifdef RENDER_BACKENDS + int v = 1; + if (OpenGLCheckbox->GetChecked()) v = 0; + else if (VulkanCheckbox->GetChecked()) v = 1; + else if (GLESCheckbox->GetChecked()) v = 2; + if (v != vid_preferbackend) vid_preferbackend = v; +#endif +} + +void SettingsPage::UpdateLanguage() +{ + LangLabel->SetText(GStrings("OPTMNU_LANGUAGE")); + GeneralLabel->SetText(GStrings("PICKER_GENERAL")); + ExtrasLabel->SetText(GStrings("PICKER_EXTRA")); + FullscreenCheckbox->SetText(GStrings("PICKER_FULLSCREEN")); + DisableAutoloadCheckbox->SetText(GStrings("PICKER_NOAUTOLOAD")); + DontAskAgainCheckbox->SetText(GStrings("PICKER_DONTASK")); + LightsCheckbox->SetText(GStrings("PICKER_LIGHTS")); + BrightmapsCheckbox->SetText(GStrings("PICKER_BRIGHTMAPS")); + WidescreenCheckbox->SetText(GStrings("PICKER_WIDESCREEN")); + +#ifdef RENDER_BACKENDS + BackendLabel->SetText(GStrings("PICKER_PREFERBACKEND")); + VulkanCheckbox->SetText(GStrings("OPTVAL_VULKAN")); + OpenGLCheckbox->SetText(GStrings("OPTVAL_OPENGL")); + GLESCheckbox->SetText(GStrings("OPTVAL_OPENGLES")); +#endif +} + +void SettingsPage::OnLanguageChanged(int i) +{ + ::language = languages[i].first.GetChars(); + GStrings.UpdateLanguage(::language); // CVAR callbacks are not active yet. + UpdateLanguage(); + Update(); + Launcher->UpdateLanguage(); +} + +void SettingsPage::OnGeometryChanged() +{ + double panelWidth = 200.0; + double y = 0.0; + double w = GetWidth(); + double h = GetHeight(); + + GeneralLabel->SetFrameGeometry(0.0, y, 190.0, GeneralLabel->GetPreferredHeight()); + ExtrasLabel->SetFrameGeometry(w - panelWidth, y, panelWidth, ExtrasLabel->GetPreferredHeight()); + y += GeneralLabel->GetPreferredHeight(); + + FullscreenCheckbox->SetFrameGeometry(0.0, y, 190.0, FullscreenCheckbox->GetPreferredHeight()); + LightsCheckbox->SetFrameGeometry(w - panelWidth, y, panelWidth, LightsCheckbox->GetPreferredHeight()); + y += FullscreenCheckbox->GetPreferredHeight(); + + DisableAutoloadCheckbox->SetFrameGeometry(0.0, y, 190.0, DisableAutoloadCheckbox->GetPreferredHeight()); + BrightmapsCheckbox->SetFrameGeometry(w - panelWidth, y, panelWidth, BrightmapsCheckbox->GetPreferredHeight()); + y += DisableAutoloadCheckbox->GetPreferredHeight(); + + DontAskAgainCheckbox->SetFrameGeometry(0.0, y, 190.0, DontAskAgainCheckbox->GetPreferredHeight()); + WidescreenCheckbox->SetFrameGeometry(w - panelWidth, y, panelWidth, WidescreenCheckbox->GetPreferredHeight()); + y += DontAskAgainCheckbox->GetPreferredHeight(); + +#ifdef RENDER_BACKENDS + BackendLabel->SetFrameGeometry(x, y, 190.0, BackendLabel->GetPreferredHeight()); + y += BackendLabel->GetPreferredHeight(); + + VulkanCheckbox->SetFrameGeometry(x, y, 190.0, VulkanCheckbox->GetPreferredHeight()); + y += VulkanCheckbox->GetPreferredHeight(); + + OpenGLCheckbox->SetFrameGeometry(x, y, 190.0, OpenGLCheckbox->GetPreferredHeight()); + y += OpenGLCheckbox->GetPreferredHeight(); + + double x = w / 2 - panelWidth / 2; + GLESCheckbox->SetFrameGeometry(x, y, 190.0, GLESCheckbox->GetPreferredHeight()); + y += GLESCheckbox->GetPreferredHeight(); +#endif + + if (!hideLanguage) + { + LangLabel->SetFrameGeometry(0.0, y, w, LangLabel->GetPreferredHeight()); + y += LangLabel->GetPreferredHeight(); + LangList->SetFrameGeometry(0.0, y, w, std::max(h - y, 0.0)); + } +} diff --git a/src/launcher/settingspage.h b/src/launcher/settingspage.h new file mode 100644 index 000000000..246fe31c5 --- /dev/null +++ b/src/launcher/settingspage.h @@ -0,0 +1,47 @@ +#pragma once + +#include + +// #define RENDER_BACKENDS + +class LauncherWindow; +class TextLabel; +class CheckboxLabel; +class ListView; + +class SettingsPage : public Widget +{ +public: + SettingsPage(LauncherWindow* launcher, int* autoloadflags); + void UpdateLanguage(); + + void Save(); + +private: + void OnLanguageChanged(int i); + void OnGeometryChanged() override; + + LauncherWindow* Launcher = nullptr; + + TextLabel* LangLabel = nullptr; + TextLabel* GeneralLabel = nullptr; + TextLabel* ExtrasLabel = nullptr; + CheckboxLabel* FullscreenCheckbox = nullptr; + CheckboxLabel* DisableAutoloadCheckbox = nullptr; + CheckboxLabel* DontAskAgainCheckbox = nullptr; + CheckboxLabel* LightsCheckbox = nullptr; + CheckboxLabel* BrightmapsCheckbox = nullptr; + CheckboxLabel* WidescreenCheckbox = nullptr; +#ifdef RENDER_BACKENDS + TextLabel* BackendLabel = nullptr; + CheckboxLabel* VulkanCheckbox = nullptr; + CheckboxLabel* OpenGLCheckbox = nullptr; + CheckboxLabel* GLESCheckbox = nullptr; +#endif + ListView* LangList = nullptr; + + int* AutoloadFlags = nullptr; + + TArray> languages; + bool hideLanguage = false; +};