mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-01 20:18:15 +01:00
Each tab is now a SettingsPage: a list of items (headers, settings, buttons, hints, links to other pages) that a function builds and views are created from. Settings are added with page->Setting(&g_Config.x), which takes the label, the kind of view, the range or choices, units, labels for special values and the default from the config. The pages keep what depends on the UI (which settings to show and when, enable rules, and behavior that needs the screen), and reach the screen through the page's SettingsPageHost. A page can link to other pages, which open on top of it in the same tab, under a bar showing where you are, like Tools > Developer tools > Graphics, where the earlier pages can be clicked to go back to them. The bar has back, search and help buttons, and the back key also goes back a page (or out of a search) before leaving the screen. Each page remembers its scroll position. In portrait there's no tab strip: a page links to the tabs, and the bar shows just the current page's title. Rotating keeps showing the same page. Moving between pages only focuses an item when navigating with a keyboard or controller. The developer tools are now pages linked from the Tools tab, instead of a screen of their own. The in-game developer menu and --start-screen=developertools open the settings on that page. The toggles of live state (the remote debugger and the MIPS tracer) show and change it through functions, and pretending to be in-game for the notification tests is a flag on the OSD. The memory map and memstick tests, only reachable from commented-out code, are removed. Search lists the matching settings from all tabs and the pages they link to, grouped by where they are. Each result goes to the setting on its page, scrolled to and highlighted (outlined, when picked with a mouse or touch), or for a page, opens it. This replaces the search tab and the old filter that hid the views that didn't match, and with them ShowSearchControls. Changing tabs leaves the search. The pages, the bar and search are in SettingsPagesDialogScreen, between the tabbed dialog screen and the settings screen, so the other tabbed screens keep plain tabs. Other visible changes: - Reset buttons that went to the wrong value now go to the real default: the touch control auto-hide delay (was 20 seconds instead of 8), the mouse wheel delay (1 ms, below its own range, instead of 80) and the UI size (0 instead of -1 on desktop). The alternative speeds get a reset button. - Units are shown on more sliders (frames, MHz, seconds, Hz), and popups no longer spell out what 0 means in the units, since the zero label does. Units of up to three characters (%, x, ms, MHz) aren't translated. - The Android HW scaler hides the scales the display is too small for, instead of cutting the list short. - Choices are translated in the setting's own section. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
215 lines
8.1 KiB
C++
215 lines
8.1 KiB
C++
// Copyright (c) 2012- PPSSPP Project.
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, version 2.0 or later versions.
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License 2.0 for more details.
|
|
|
|
// A copy of the GPL 2.0 should have been included with the program.
|
|
// If not, see http://www.gnu.org/licenses/
|
|
|
|
// Official git repository and contact information can be found at
|
|
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
|
|
|
#pragma once
|
|
|
|
#include <deque>
|
|
#include <functional>
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <vector>
|
|
|
|
#include "Common/Data/Text/I18n.h"
|
|
#include "Common/Render/TextureAtlas.h"
|
|
|
|
namespace UI {
|
|
class View;
|
|
class ViewGroup;
|
|
struct EventParams;
|
|
}
|
|
|
|
class Path;
|
|
class ScreenManager;
|
|
class SettingsPage;
|
|
|
|
// What the pages' handlers can do on the screen showing them. Lives as long as the views do.
|
|
class SettingsPageHost {
|
|
public:
|
|
virtual ~SettingsPageHost() {}
|
|
virtual ScreenManager *PageScreenManager() = 0;
|
|
// For System_ requests (like file dialogs) whose results go to the views.
|
|
virtual int PageRequesterToken() = 0;
|
|
// Builds the page again, for when what's on it changed.
|
|
virtual void RecreatePageViews() = 0;
|
|
// The game whose settings are being edited, if any.
|
|
virtual const Path &PageGamePath() const = 0;
|
|
// For a setting that only takes effect after a restart: asks to restart, or else calls otherwise
|
|
// (which usually puts the setting back).
|
|
virtual void RestartOrDo(std::function<void()> otherwise) = 0;
|
|
};
|
|
|
|
// Translatable text, kept as a key so it can be looked up both in English and translated
|
|
// (for search) as well as when it's shown.
|
|
struct SettingText {
|
|
SettingText() {}
|
|
SettingText(const char *key) : key(key) {}
|
|
SettingText(I18NCat cat, const char *key, const char *def = nullptr) : cat(cat), key(key), def(def), hasCat(true) {}
|
|
// Shown as is, without translation (like module names).
|
|
static SettingText Raw(const char *text) {
|
|
SettingText t(text);
|
|
t.raw = true;
|
|
return t;
|
|
}
|
|
|
|
// Texts without a category use the page's.
|
|
std::string_view Translate(I18NCat pageCat) const;
|
|
std::string_view English() const;
|
|
bool empty() const { return !key; }
|
|
|
|
I18NCat cat = I18NCat::NONE;
|
|
const char *key = nullptr;
|
|
const char *def = nullptr;
|
|
bool hasCat = false;
|
|
bool raw = false;
|
|
};
|
|
|
|
enum class SettingType {
|
|
Header,
|
|
Bool,
|
|
IntChoice,
|
|
StringChoice,
|
|
IntSlider,
|
|
FloatSlider,
|
|
Choice, // A button. onChange is called on click.
|
|
Info,
|
|
Hint, // Explanatory text attached to the previous item.
|
|
Custom,
|
|
Link, // Opens another page.
|
|
};
|
|
|
|
// Describes one item in a settings page. Views are only created from this in CreateSettingViews,
|
|
// so a page can also be inspected without creating any (for search).
|
|
struct SettingItem {
|
|
SettingType type;
|
|
SettingText text;
|
|
void *ptr = nullptr; // bool *, int * or std::string *, depending on type.
|
|
|
|
// IntChoice. The choices are translated in the same category as the text.
|
|
const char *const *choices = nullptr;
|
|
int minVal = 0;
|
|
int numChoices = 0;
|
|
|
|
// StringChoice. If values is empty, the names are stored.
|
|
std::vector<std::string> choiceNames;
|
|
std::vector<std::string> choiceValues;
|
|
|
|
// IntSlider. If defaultValue isn't set, it's taken from the config.
|
|
int minValue = 0;
|
|
int maxValue = 0;
|
|
int defaultValue = 0;
|
|
bool hasDefault = false;
|
|
int step = 1;
|
|
std::string format;
|
|
SettingText zeroLabel;
|
|
SettingText negativeLabel;
|
|
const int *restrictTo = nullptr;
|
|
size_t restrictCount = 0;
|
|
|
|
// FloatSlider
|
|
float fMinValue = 0.0f;
|
|
float fMaxValue = 0.0f;
|
|
float fDefaultValue = 0.0f;
|
|
float fStep = 0.0f;
|
|
|
|
// Both slider types. Already translated.
|
|
std::string units;
|
|
bool liveUpdate = false;
|
|
|
|
// Choice
|
|
ImageID image;
|
|
|
|
// Info
|
|
std::string rightText;
|
|
|
|
// Custom
|
|
std::function<UI::View *(UI::ViewGroup *parent)> createCustom;
|
|
|
|
// Link: builds the page it opens, whose texts default to linkCat. helpTag is the docs page for it and the
|
|
// pages under it, if not the same as the linking page's.
|
|
std::function<void(SettingsPage *)> linkBuild;
|
|
I18NCat linkCat = I18NCat::NONE;
|
|
const char *helpTag = nullptr;
|
|
|
|
// Bool, instead of ptr: for state that lives elsewhere, like whether a server runs.
|
|
std::function<bool()> getBool;
|
|
std::function<void(bool)> setBool;
|
|
|
|
bool *enabledPtr = nullptr;
|
|
bool *disabledPtr = nullptr;
|
|
std::function<bool()> enabledFunc;
|
|
// Called on click (Bool, Choice), choice (choices) or change (sliders).
|
|
std::function<void(UI::EventParams &)> onChange;
|
|
// From the config, for settings described there. Called before onChange.
|
|
void (*configOnChanged)() = nullptr;
|
|
// For tweaks the description doesn't cover, called after the view is created.
|
|
std::function<void(UI::View *)> setup;
|
|
|
|
SettingItem &Enabled(bool *ptr) { enabledPtr = ptr; return *this; }
|
|
SettingItem &Disabled(bool *ptr) { disabledPtr = ptr; return *this; }
|
|
SettingItem &EnabledFunc(std::function<bool()> func) { enabledFunc = std::move(func); return *this; }
|
|
SettingItem &OnChange(std::function<void(UI::EventParams &)> func) { onChange = std::move(func); return *this; }
|
|
SettingItem &OnClick(std::function<void(UI::EventParams &)> func) { onChange = std::move(func); return *this; }
|
|
SettingItem &Setup(std::function<void(UI::View *)> func) { setup = std::move(func); return *this; }
|
|
SettingItem &Default(int value) { defaultValue = value; hasDefault = true; return *this; }
|
|
SettingItem &Step(int value) { step = value; return *this; }
|
|
SettingItem &Format(std::string_view fmt) { format = fmt; return *this; }
|
|
SettingItem &LiveUpdate() { liveUpdate = true; return *this; }
|
|
SettingItem &RestrictTo(const int *values, size_t count) { restrictTo = values; restrictCount = count; return *this; }
|
|
};
|
|
|
|
// A list of settings items. Texts without a category get the page's.
|
|
class SettingsPage {
|
|
public:
|
|
SettingsPage(I18NCat defaultCat, SettingsPageHost *host) : defaultCat_(defaultCat), host_(host) {}
|
|
|
|
// Without a title, just starts a new group.
|
|
SettingItem &Header(SettingText text = SettingText());
|
|
// Settings described in the config: the label, kind of view, range or choices, and default come from there.
|
|
SettingItem &Setting(bool *value);
|
|
SettingItem &Setting(int *value);
|
|
SettingItem &Setting(float *value);
|
|
// For string settings with choices that are only known at runtime, like devices. The names are shown as
|
|
// is, untranslated. If values is empty, the names are stored.
|
|
SettingItem &Setting(std::string *value, std::vector<std::string> names, std::vector<std::string> values = {});
|
|
// For values that aren't config settings.
|
|
SettingItem &Bool(bool *value, SettingText text);
|
|
SettingItem &Bool(SettingText text, std::function<bool()> get, std::function<void(bool)> set);
|
|
SettingItem &IntSlider(int *value, int minValue, int maxValue, SettingText text);
|
|
SettingItem &Choice(SettingText text, ImageID image = ImageID::invalid());
|
|
SettingItem &Info(SettingText text, std::string_view rightText);
|
|
SettingItem &Hint(SettingText text);
|
|
// For anything the other types can't describe. The text is only used for search. The view
|
|
// returned is the one a following Hint is attached to, and the one search results lead to.
|
|
SettingItem &Custom(SettingText text, std::function<UI::View *(UI::ViewGroup *parent)> create);
|
|
// Opens another page, built by build, on top of this one. The text is the new page's title.
|
|
SettingItem &Link(SettingText text, I18NCat cat, std::function<void(SettingsPage *)> build);
|
|
|
|
I18NCat DefaultCat() const { return defaultCat_; }
|
|
SettingsPageHost *Host() const { return host_; }
|
|
const std::deque<SettingItem> &Items() const { return items_; }
|
|
|
|
private:
|
|
SettingItem &Add(SettingType type, SettingText text);
|
|
|
|
I18NCat defaultCat_;
|
|
SettingsPageHost *host_;
|
|
std::deque<SettingItem> items_; // A deque so references stay valid while adding.
|
|
};
|
|
|
|
// If views is set, it gets the view created for each item (or null), in the same order.
|
|
void CreateSettingViews(const SettingsPage &page, UI::ViewGroup *parent, ScreenManager *screenManager, std::vector<UI::View *> *views = nullptr);
|