Merge branch 'master' into TemporaryHackishBranch

# Conflicts:
#	Core/Config.cpp
#	Core/Config.h
#	UI/ControlMappingScreen.cpp
#	UI/EmuScreen.cpp
#	UI/GameSettingsScreen.cpp
#	android/assets/ui_atlas.meta
#	android/assets/ui_atlas.zim
#	assets/ui_atlas.meta
#	assets/ui_atlas.zim
This commit is contained in:
LunaMoo committed 2021-07-17 19:08:58 +02:00
commit 4fb6e0c242
198 files changed
+6323 -2862

No files matched your search

+67 -154
View File
@@ -49,8 +49,8 @@
#include "UI/TouchControlVisibilityScreen.h"
#include "UI/TiltAnalogSettingsScreen.h"
#include "UI/TiltEventProcessor.h"
#include "UI/ComboKeyMappingScreen.h"
#include "UI/GPUDriverTestScreen.h"
#include "UI/MemStickScreen.h"
#include "Common/File/FileUtil.h"
#include "Common/OSVersion.h"
@@ -79,6 +79,14 @@
#include "Windows/W32Util/ShellUtil.h"
#endif
#if PPSSPP_PLATFORM(ANDROID)
#include "android/jni/AndroidAudio.h"
extern AndroidAudioState *g_audioState;
#endif
GameSettingsScreen::GameSettingsScreen(const Path &gamePath, std::string gameID, bool editThenRestore)
: UIDialogScreenWithGameBackground(gamePath), gameID_(gameID), enableReports_(false), editThenRestore_(editThenRestore) {
lastVertical_ = UseVerticalLayout();
@@ -653,7 +661,13 @@ void GameSettingsScreen::CreateViews() {
//#if defined(__ANDROID__)
CheckBox *extraAudio = audioSettings->Add(new CheckBox(&g_Config.bExtraAudioBuffering, a->T("AudioBufferingForBluetooth", "Bluetooth-friendly buffer (slower)")));
extraAudio->SetEnabledPtr(&g_Config.bEnableSound);
//#endif
//#endif#if defined(__ANDROID__)
// Show OpenSL debug info
const std::string audioErrorStr = AndroidAudio_GetErrorString(g_audioState);
if (!audioErrorStr.empty()) {
audioSettings->Add(new InfoItem(a->T("Audio Error"), audioErrorStr));
}
#endif
PopupSliderChoice *sasVol = audioSettings->Add(new PopupSliderChoice(&g_Config.iSASVolume, 0, MAX_CONFIG_VOLUME, a->T("SAS volume"), screenManager()));
sasVol->SetEnabledPtr(&g_Config.bEnableSound);
@@ -670,6 +684,7 @@ void GameSettingsScreen::CreateViews() {
tabHolder->AddTab(ms->T("Controls"), controlsSettingsScroll);
controlsSettings->Add(new ItemHeader(ms->T("Controls")));
controlsSettings->Add(new Choice(co->T("Control Mapping")))->OnClick.Handle(this, &GameSettingsScreen::OnControlMapping);
controlsSettings->Add(new Choice(co->T("Calibrate Analog Stick")))->OnClick.Handle(this, &GameSettingsScreen::OnCalibrateAnalogs);
if (!g_Config.bSimpleUI) {
#if defined(USING_WIN_UI)
@@ -701,7 +716,7 @@ void GameSettingsScreen::CreateViews() {
if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) != DEVICE_TYPE_TV) {
controlsSettings->Add(new ItemHeader(co->T("OnScreen", "On-Screen Touch Controls")));
controlsSettings->Add(new CheckBox(&g_Config.bShowTouchControls, co->T("OnScreen", "On-Screen Touch Controls")));
layoutEditorChoice_ = controlsSettings->Add(new Choice(co->T("Custom layout...")));
layoutEditorChoice_ = controlsSettings->Add(new Choice(co->T("Customize Touch Controls")));
layoutEditorChoice_->OnClick.Handle(this, &GameSettingsScreen::OnTouchControlLayout);
layoutEditorChoice_->SetEnabledPtr(&g_Config.bShowTouchControls);
@@ -709,11 +724,6 @@ void GameSettingsScreen::CreateViews() {
CheckBox *floatingAnalog = controlsSettings->Add(new CheckBox(&g_Config.bAutoCenterTouchAnalog, co->T("Auto-centering analog stick")));
floatingAnalog->SetEnabledPtr(&g_Config.bShowTouchControls);
// Combo key setup
Choice *comboKey = controlsSettings->Add(new Choice(co->T("Combo Key Setup")));
comboKey->OnClick.Handle(this, &GameSettingsScreen::OnComboKey);
comboKey->SetEnabledPtr(&g_Config.bShowTouchControls);
// On non iOS systems, offer to let the user see this button.
// Some Windows touch devices don't have a back button or other button to call up the menu.
if (System_GetPropertyBool(SYSPROP_HAS_BACK_BUTTON)) {
@@ -741,25 +751,6 @@ void GameSettingsScreen::CreateViews() {
style->SetEnabledPtr(&g_Config.bShowTouchControls);
}
#ifdef _WIN32
static const char *inverseDeadzoneModes[] = { "Off", "X", "Y", "X + Y" };
controlsSettings->Add(new ItemHeader(co->T("DInput Analog Settings", "DInput Analog Settings")));
controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fDInputAnalogDeadzone, 0.0f, 1.0f, co->T("Deadzone Radius"), 0.01f, screenManager(), "/ 1.0"));
controlsSettings->Add(new PopupMultiChoice(&g_Config.iDInputAnalogInverseMode, co->T("Analog Mapper Mode"), inverseDeadzoneModes, 0, ARRAY_SIZE(inverseDeadzoneModes), co->GetName(), screenManager()));
controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fDInputAnalogInverseDeadzone, 0.0f, 1.0f, co->T("Analog Mapper Low End", "Analog Mapper Low End (Inverse Deadzone)"), 0.01f, screenManager(), "/ 1.0"));
controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fDInputAnalogSensitivity, 0.0f, 10.0f, co->T("Analog Mapper High End", "Analog Mapper High End (Axis Sensitivity)"), 0.01f, screenManager(), "x"));
controlsSettings->Add(new ItemHeader(co->T("XInput Analog Settings", "XInput Analog Settings")));
controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fXInputAnalogDeadzone, 0.0f, 1.0f, co->T("Deadzone Radius"), 0.01f, screenManager(), "/ 1.0"));
controlsSettings->Add(new PopupMultiChoice(&g_Config.iXInputAnalogInverseMode, co->T("Analog Mapper Mode"), inverseDeadzoneModes, 0, ARRAY_SIZE(inverseDeadzoneModes), co->GetName(), screenManager()));
controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fXInputAnalogInverseDeadzone, 0.0f, 1.0f, co->T("Analog Mapper Low End", "Analog Mapper Low End (Inverse Deadzone)"), 0.01f, screenManager(), "/ 1.0"));
controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fXInputAnalogSensitivity, 0.0f, 10.0f, co->T("Analog Mapper High End", "Analog Mapper High End (Axis Sensitivity)"), 0.01f, screenManager(), "x"));
#else
controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fXInputAnalogSensitivity, 0.0f, 10.0f, co->T("Analog Axis Sensitivity", "Analog Axis Sensitivity"), 0.01f, screenManager(), "x"));
#endif
controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fAnalogAutoRotSpeed, 0.0f, 25.0f, co->T("Analog auto-rotation speed"), 1.0f, screenManager()));
controlsSettings->Add(new ItemHeader(co->T("Keyboard", "Keyboard Control Settings")));
#if defined(USING_WIN_UI)
controlsSettings->Add(new CheckBox(&g_Config.bIgnoreWindowsKey, co->T("Ignore Windows Key")));
@@ -793,7 +784,7 @@ void GameSettingsScreen::CreateViews() {
networkingSettings->Add(new ItemHeader(ms->T("Networking")));
networkingSettings->Add(new Choice(n->T("Adhoc Multiplayer forum")))->OnClick.Handle(this, &GameSettingsScreen::OnAdhocGuides);
networkingSettings->Add(new Choice(n->T("PPSSPP Ad-Hoc Wiki Page")))->OnClick.Handle(this, &GameSettingsScreen::OnAdhocGuides);
networkingSettings->Add(new CheckBox(&g_Config.bEnableWlan, n->T("Enable networking", "Enable networking/wlan (beta)")));
networkingSettings->Add(new ChoiceWithValueDisplay(&g_Config.sMACAddress, n->T("Change Mac Address"), (const char*)nullptr))->OnClick.Handle(this, &GameSettingsScreen::OnChangeMacAddress);
@@ -922,7 +913,7 @@ void GameSettingsScreen::CreateViews() {
systemSettings->Add(new ItemHeader(sy->T("Emulation")));
systemSettings->Add(new CheckBox(&g_Config.bFastMemory, sy->T("Fast Memory", "Fast Memory (Unstable)")))->OnClick.Handle(this, &GameSettingsScreen::OnJitAffectingSetting);
systemSettings->Add(new CheckBox(&g_Config.bFastMemory, sy->T("Fast Memory", "Fast Memory")))->OnClick.Handle(this, &GameSettingsScreen::OnJitAffectingSetting);
systemSettings->Add(new CheckBox(&g_Config.bIgnoreBadMemAccess, sy->T("Ignore bad memory accesses")));
systemSettings->Add(new CheckBox(&g_Config.bSeparateIOThread, sy->T("I/O on thread (experimental)")))->SetEnabled(!PSP_IsInited());
@@ -939,38 +930,14 @@ void GameSettingsScreen::CreateViews() {
PopupSliderChoice *rewindFreq = systemSettings->Add(new PopupSliderChoice(&g_Config.iRewindFlipFrequency, 0, 1800, sy->T("Rewind Snapshot Frequency", "Rewind Snapshot Frequency (mem hog)"), screenManager(), sy->T("frames, 0:off")));
rewindFreq->SetZeroLabel(sy->T("Off"));
systemSettings->Add(new ItemHeader(sy->T("PSP Memory Stick")));
systemSettings->Add(new CheckBox(&g_Config.bMemStickInserted, sy->T("Memory Stick inserted")));
systemSettings->Add(new PopupSliderChoice(&g_Config.iMemStickSizeGB, 1, 32, sy->T("Change Memory Stick Size", "Change Memory Stick Size(GB)"), screenManager(), "GB"));
systemSettings->Add(new PopupSliderChoice(&g_Config.iMemStickSizeGB, 1, 32, sy->T("Change Memory Stick Size", "Memory Stick Size (GB)"), screenManager(), "GB"));
}
systemSettings->Add(new ItemHeader(sy->T("General")));
#if PPSSPP_PLATFORM(ANDROID)
if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_MOBILE) {
static const char *screenRotation[] = {"Auto", "Landscape", "Portrait", "Landscape Reversed", "Portrait Reversed", "Landscape Auto"};
PopupMultiChoice *rot = systemSettings->Add(new PopupMultiChoice(&g_Config.iScreenRotation, co->T("Screen Rotation"), screenRotation, 0, ARRAY_SIZE(screenRotation), co->GetName(), screenManager()));
rot->OnChoice.Handle(this, &GameSettingsScreen::OnScreenRotation);
if (System_GetPropertyBool(SYSPROP_SUPPORTS_SUSTAINED_PERF_MODE)) {
systemSettings->Add(new CheckBox(&g_Config.bSustainedPerformanceMode, sy->T("Sustained performance mode")))->OnClick.Handle(this, &GameSettingsScreen::OnSustainedPerformanceModeChange);
}
}
#endif
if (!g_Config.bSimpleUI) {
systemSettings->Add(new CheckBox(&g_Config.bCheckForNewVersion, sy->T("VersionCheck", "Check for new versions of PPSSPP")));
}
systemSettings->Add(new Choice(sy->T("Restore Default Settings")))->OnClick.Handle(this, &GameSettingsScreen::OnRestoreDefaultSettings);
if (!g_Config.bSimpleUI) {
systemSettings->Add(new CheckBox(&g_Config.bEnableStateUndo, sy->T("Savestate slot backups")));
static const char *autoLoadSaveStateChoices[] = { "Off", "Oldest Save", "Newest Save", "Slot 1", "Slot 2", "Slot 3", "Slot 4", "Slot 5" };
systemSettings->Add(new PopupMultiChoice(&g_Config.iAutoLoadSaveState, sy->T("Auto Load Savestate"), autoLoadSaveStateChoices, 0, ARRAY_SIZE(autoLoadSaveStateChoices), sy->GetName(), screenManager()));
#if defined(USING_WIN_UI) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID)
systemSettings->Add(new CheckBox(&g_Config.bBypassOSKWithKeyboard, sy->T("Use system native keyboard")));
#endif
#if PPSSPP_PLATFORM(ANDROID)
}#if PPSSPP_PLATFORM(ANDROID)
memstickDisplay_ = g_Config.memStickDirectory.ToVisualString();
auto memstickPath = systemSettings->Add(new ChoiceWithValueDisplay(&memstickDisplay_, sy->T("Change Memory Stick folder"), (const char *)nullptr));
auto memstickPath = systemSettings->Add(new ChoiceWithValueDisplay(&memstickDisplay_, sy->T("Change Memory Stick folder", "Memory Stick folder"), (const char *)nullptr));
memstickPath->SetEnabled(!PSP_IsInited());
memstickPath->OnClick.Handle(this, &GameSettingsScreen::OnChangeMemStickDir);
#elif defined(_WIN32) && !PPSSPP_PLATFORM(UWP)
@@ -1017,6 +984,29 @@ void GameSettingsScreen::CreateViews() {
}
}
#endif
systemSettings->Add(new ItemHeader(sy->T("General")));
#if PPSSPP_PLATFORM(ANDROID)
if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_MOBILE) {
static const char *screenRotation[] = { "Auto", "Landscape", "Portrait", "Landscape Reversed", "Portrait Reversed", "Landscape Auto" };
PopupMultiChoice *rot = systemSettings->Add(new PopupMultiChoice(&g_Config.iScreenRotation, co->T("Screen Rotation"), screenRotation, 0, ARRAY_SIZE(screenRotation), co->GetName(), screenManager()));
rot->OnChoice.Handle(this, &GameSettingsScreen::OnScreenRotation);
if (System_GetPropertyBool(SYSPROP_SUPPORTS_SUSTAINED_PERF_MODE)) {
systemSettings->Add(new CheckBox(&g_Config.bSustainedPerformanceMode, sy->T("Sustained performance mode")))->OnClick.Handle(this, &GameSettingsScreen::OnSustainedPerformanceModeChange);
}
}
#endif
if (!g_Config.bSimpleUI) {
systemSettings->Add(new CheckBox(&g_Config.bCheckForNewVersion, sy->T("VersionCheck", "Check for new versions of PPSSPP")));
}
systemSettings->Add(new Choice(sy->T("Restore Default Settings")))->OnClick.Handle(this, &GameSettingsScreen::OnRestoreDefaultSettings);
systemSettings->Add(new CheckBox(&g_Config.bEnableStateUndo, sy->T("Savestate slot backups")));
static const char *autoLoadSaveStateChoices[] = { "Off", "Oldest Save", "Newest Save", "Slot 1", "Slot 2", "Slot 3", "Slot 4", "Slot 5" };
systemSettings->Add(new PopupMultiChoice(&g_Config.iAutoLoadSaveState, sy->T("Auto Load Savestate"), autoLoadSaveStateChoices, 0, ARRAY_SIZE(autoLoadSaveStateChoices), sy->GetName(), screenManager()));
#if defined(USING_WIN_UI) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID)
systemSettings->Add(new CheckBox(&g_Config.bBypassOSKWithKeyboard, sy->T("Use system native keyboard")));
#endif
#if PPSSPP_ARCH(AMD64)
systemSettings->Add(new CheckBox(&g_Config.bCacheFullIsoInRam, sy->T("Cache ISO in RAM", "Cache full ISO in RAM")))->SetEnabled(!PSP_IsInited());
@@ -1109,7 +1099,8 @@ void RecreateActivity() {
}
UI::EventReturn GameSettingsScreen::OnAdhocGuides(UI::EventParams &e) {
LaunchBrowser("https://forums.ppsspp.org/forumdisplay.php?fid=34");
auto n = GetI18NCategory("Networking");
LaunchBrowser(n->T("MultiplayerHowToURL", "https://github.com/hrydgard/ppsspp/wiki/How-to-play-multiplayer-games-with-PPSSPP"));
return UI::EVENT_DONE;
}
@@ -1144,40 +1135,12 @@ UI::EventReturn GameSettingsScreen::OnJitAffectingSetting(UI::EventParams &e) {
return UI::EVENT_DONE;
}
#if PPSSPP_PLATFORM(ANDROID)
UI::EventReturn GameSettingsScreen::OnChangeMemStickDir(UI::EventParams &e) {
auto sy = GetI18NCategory("System");
System_InputBoxGetString(sy->T("Memory Stick Folder"), g_Config.memStickDirectory.ToString(), [&](bool result, const std::string &value) {
auto sy = GetI18NCategory("System");
auto di = GetI18NCategory("Dialog");
if (result) {
std::string newPath = value;
size_t pos = newPath.find_last_not_of("/");
// Gotta have at least something but a /, and also needs to start with a /.
if (newPath.empty() || pos == newPath.npos || newPath[0] != '/') {
settingInfo_->Show(sy->T("ChangingMemstickPathInvalid", "That path couldn't be used to save Memory Stick files."), nullptr);
return;
}
if (pos != newPath.size() - 1) {
newPath = newPath.substr(0, pos + 1);
}
pendingMemstickFolder_ = newPath;
std::string promptMessage = sy->T("ChangingMemstickPath", "Save games, save states, and other data will not be copied to this folder.\n\nChange the Memory Stick folder?");
if (!File::Exists(Path(newPath))) {
promptMessage = sy->T("ChangingMemstickPathNotExists", "That folder doesn't exist yet.\n\nSave games, save states, and other data will not be copied to this folder.\n\nCreate a new Memory Stick folder?");
}
// Add the path for clarity and proper confirmation.
promptMessage += "\n\n" + newPath + "/";
screenManager()->push(new PromptScreen(promptMessage, di->T("Yes"), di->T("No"), std::bind(&GameSettingsScreen::CallbackMemstickFolder, this, std::placeholders::_1)));
}
});
screenManager()->push(new MemStickScreen());
return UI::EVENT_DONE;
}
#elif defined(_WIN32) && !PPSSPP_PLATFORM(UWP)
#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP)
UI::EventReturn GameSettingsScreen::OnSavePathMydoc(UI::EventParams &e) {
const Path &PPSSPPpath = File::GetExeDirectory();
@@ -1242,12 +1205,8 @@ UI::EventReturn GameSettingsScreen::OnChangeBackground(UI::EventParams &e) {
const Path bgJpg = GetSysDirectory(DIRECTORY_SYSTEM) / "background.jpg";
if (File::Exists(bgPng) || File::Exists(bgJpg)) {
if (File::Exists(bgPng)) {
File::Delete(bgPng);
}
if (File::Exists(bgJpg)) {
File::Delete(bgJpg);
}
File::Delete(bgPng);
File::Delete(bgJpg);
NativeMessageReceived("bgImage_updated", "");
} else {
@@ -1354,10 +1313,13 @@ void GameSettingsScreen::CallbackMemstickFolder(bool yes) {
}
File::Delete(Path(testWriteFile));
File::WriteDataToFile(true, pendingMemstickFolder_.c_str(), (unsigned int)pendingMemstickFolder_.size(), memstickDirFile);
// Save so the settings, at least, are transferred.
g_Config.memStickDirectory = Path(pendingMemstickFolder_);
g_Config.Save("MemstickPathChanged");
if (!File::WriteDataToFile(true, pendingMemstickFolder_.c_str(), (unsigned int)pendingMemstickFolder_.size(), memstickDirFile)) {
WARN_LOG(SYSTEM, "Failed to write memstick folder to '%s'", memstickDirFile.c_str());
} else {
// Save so the settings, at least, are transferred.
g_Config.memStickDirectory = Path(pendingMemstickFolder_);
g_Config.Save("MemstickPathChanged");
}
screenManager()->RecreateAllViews();
}
}
@@ -1547,11 +1509,6 @@ UI::EventReturn GameSettingsScreen::OnChangeMacAddress(UI::EventParams &e) {
return UI::EVENT_DONE;
}
UI::EventReturn GameSettingsScreen::OnComboKey(UI::EventParams &e) {
screenManager()->push(new ComboKeyScreen(&g_Config.iComboMode));
return UI::EVENT_DONE;
}
UI::EventReturn GameSettingsScreen::OnLanguage(UI::EventParams &e) {
auto dev = GetI18NCategory("Developer");
auto langScreen = new NewLanguageScreen(dev->T("Language"));
@@ -1616,6 +1573,11 @@ UI::EventReturn GameSettingsScreen::OnControlMapping(UI::EventParams &e) {
return UI::EVENT_DONE;
}
UI::EventReturn GameSettingsScreen::OnCalibrateAnalogs(UI::EventParams &e) {
screenManager()->push(new AnalogSetupScreen());
return UI::EVENT_DONE;
}
UI::EventReturn GameSettingsScreen::OnTouchControlLayout(UI::EventParams &e) {
screenManager()->push(new TouchControlLayoutScreen());
return UI::EVENT_DONE;
@@ -1955,7 +1917,7 @@ void HostnameSelectScreen::CreatePopupContents(UI::ViewGroup *parent) {
buttonsRow2->Add(new Button(di->T("Toggle List")))->OnClick.Handle(this, &HostnameSelectScreen::OnShowIPListClick);
buttonsRow2->Add(new Spacer(new LinearLayoutParams(1.0, G_RIGHT)));
std::vector<std::string> listIP = {"myneighborsushicat.com", "socom.cc", "localhost"}; // TODO: Add some saved recent history too?
std::vector<std::string> listIP = {"socom.cc", "myneighborsushicat.com", "localhost"}; // TODO: Add some saved recent history too?
net::GetIPList(listIP);
ipRows_ = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(1.0));
ScrollView* scrollView = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT));
@@ -2126,52 +2088,3 @@ void HostnameSelectScreen::OnCompleted(DialogResult result) {
if (result == DR_OK)
*value_ = StripSpaces(addrView_->GetText());
}
SettingInfoMessage::SettingInfoMessage(int align, UI::AnchorLayoutParams *lp)
: UI::LinearLayout(UI::ORIENT_HORIZONTAL, lp) {
using namespace UI;
SetSpacing(0.0f);
Add(new UI::Spacer(10.0f));
text_ = Add(new UI::TextView("", align, false, new LinearLayoutParams(1.0, Margins(0, 10))));
Add(new UI::Spacer(10.0f));
}
void SettingInfoMessage::Show(const std::string &text, UI::View *refView) {
if (refView) {
Bounds b = refView->GetBounds();
const UI::AnchorLayoutParams *lp = GetLayoutParams()->As<UI::AnchorLayoutParams>();
if (b.y >= cutOffY_) {
ReplaceLayoutParams(new UI::AnchorLayoutParams(lp->width, lp->height, lp->left, 80.0f, lp->right, lp->bottom, lp->center));
} else {
ReplaceLayoutParams(new UI::AnchorLayoutParams(lp->width, lp->height, lp->left, dp_yres - 80.0f - 40.0f, lp->right, lp->bottom, lp->center));
}
}
text_->SetText(text);
timeShown_ = time_now_d();
}
void SettingInfoMessage::Draw(UIContext &dc) {
static const double FADE_TIME = 1.0;
static const float MAX_ALPHA = 0.9f;
// Let's show longer messages for more time (guesstimate at reading speed.)
// Note: this will give multibyte characters more time, but they often have shorter words anyway.
double timeToShow = std::max(1.5, text_->GetText().size() * 0.05);
double sinceShow = time_now_d() - timeShown_;
float alpha = MAX_ALPHA;
if (timeShown_ == 0.0 || sinceShow > timeToShow + FADE_TIME) {
alpha = 0.0f;
} else if (sinceShow > timeToShow) {
alpha = MAX_ALPHA - MAX_ALPHA * (float)((sinceShow - timeToShow) / FADE_TIME);
}
if (alpha >= 0.1f) {
UI::Style style = dc.theme->popupTitle;
style.background.color = colorAlpha(style.background.color, alpha - 0.1f);
dc.FillRect(style.background, bounds_);
}
text_->SetTextColor(whiteAlpha(alpha));
ViewGroup::Draw(dc);
}