Skip to content

Commit

Permalink
Merge pull request #17605 from hrydgard/osd-refactoring
Browse files Browse the repository at this point in the history
On-screen messages refactoring
  • Loading branch information
hrydgard authored Jun 20, 2023
2 parents d7e4055 + 8fa7cb2 commit 9df01a5
Show file tree
Hide file tree
Showing 35 changed files with 288 additions and 203 deletions.
69 changes: 69 additions & 0 deletions Common/System/Request.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,78 @@
#include <cstring>

#include "Common/System/Request.h"
#include "Common/System/System.h"
#include "Common/Log.h"
#include "Common/File/Path.h"
#include "Common/TimeUtil.h"

RequestManager g_requestManager;
OnScreenDisplay g_OSD;

void OnScreenDisplay::Update() {
std::lock_guard<std::mutex> guard(mutex_);

double now = time_now_d();
for (auto iter = entries_.begin(); iter != entries_.end(); ) {
if (now >= iter->endTime) {
iter = entries_.erase(iter);
} else {
iter++;
}
}
}

std::vector<OnScreenDisplay::Entry> OnScreenDisplay::Entries() {
std::lock_guard<std::mutex> guard(mutex_);
return entries_; // makes a copy.
}

void OnScreenDisplay::Show(OSDType type, const std::string &text, float duration_s, const char *id) {
// Automatic duration based on type.
if (duration_s <= 0.0f) {
switch (type) {
case OSDType::MESSAGE_ERROR:
case OSDType::MESSAGE_WARNING:
duration_s = 3.0f;
break;
case OSDType::MESSAGE_FILE_LINK:
duration_s = 5.0f;
break;
case OSDType::MESSAGE_SUCCESS:
duration_s = 2.0f;
break;
default:
duration_s = 1.5f;
break;
}
}

double now = time_now_d();
std::lock_guard<std::mutex> guard(mutex_);
if (id) {
for (auto iter = entries_.begin(); iter != entries_.end(); ++iter) {
if (iter->id && !strcmp(iter->id, id)) {
Entry msg = *iter;
msg.endTime = now + duration_s;
msg.text = text;
entries_.erase(iter);
entries_.insert(entries_.begin(), msg);
return;
}
}
}

Entry msg;
msg.text = text;
msg.endTime = now + duration_s;
msg.id = id;
entries_.insert(entries_.begin(), msg);
}

void OnScreenDisplay::ShowOnOff(const std::string &message, bool on, float duration_s) {
// TODO: translate "on" and "off"? Or just get rid of this whole thing?
Show(OSDType::MESSAGE_INFO, message + ": " + (on ? "on" : "off"), duration_s);
}

const char *RequestTypeAsString(SystemRequestType type) {
switch (type) {
Expand Down
41 changes: 40 additions & 1 deletion Common/System/System.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <vector>
#include <functional>
#include <cstdint>
#include <mutex>

// Platform integration

Expand Down Expand Up @@ -212,7 +213,45 @@ void System_PostUIMessage(const std::string &message, const std::string &param);

// Shows a visible message to the user.
// The default implementation in NativeApp.cpp uses our "osm" system (on screen messaging).
void System_NotifyUserMessage(const std::string &message, float duration = 1.0f, uint32_t color = 0x00FFFFFF, const char *id = nullptr);
enum class OSDType {
MESSAGE_INFO,
MESSAGE_SUCCESS,
MESSAGE_WARNING,
MESSAGE_ERROR,
MESSAGE_ERROR_DUMP, // displays lots of text (after the first line), small size
MESSAGE_FILE_LINK,
// PROGRESS_BAR,
// PROGRESS_INDETERMINATE,
};

// Data holder for on-screen messages.
class OnScreenDisplay {
public:
// If you specify 0.0f as duration, a duration will be chosen automatically depending on type.
void Show(OSDType type, const std::string &message, float duration_s = 0.0f, const char *id = nullptr);
void ShowOnOff(const std::string &message, bool on, float duration_s = 0.0f);

bool IsEmpty() const { return entries_.empty(); } // Shortcut to skip rendering.

// Call this every frame, cleans up old entries.
void Update();

struct Entry {
OSDType type;
std::string text;
const char *id;
double endTime;
double duration;
float progress;
};
std::vector<Entry> Entries();

private:
std::vector<Entry> entries_;
std::mutex mutex_;
};

extern OnScreenDisplay g_OSD;

// For these functions, most platforms will use the implementation provided in UI/AudioCommon.cpp,
// no need to implement separately.
Expand Down
20 changes: 20 additions & 0 deletions Common/UI/Screen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ void ScreenManager::update() {
stack_.back().screen->update();
}

if (overlayScreen_) {
overlayScreen_->update();
}

g_iconCache.FrameUpdate();
}

Expand Down Expand Up @@ -174,6 +178,9 @@ void ScreenManager::render() {
stack_.back().screen->render();
if (postRenderCb_)
postRenderCb_(getUIContext(), postRenderUserdata_);
if (overlayScreen_) {
overlayScreen_->render();
}
backback.screen->postRender();
break;
}
Expand All @@ -183,6 +190,9 @@ void ScreenManager::render() {
stack_.back().screen->render();
if (postRenderCb_)
postRenderCb_(getUIContext(), postRenderUserdata_);
if (overlayScreen_) {
overlayScreen_->render();
}
stack_.back().screen->postRender();
break;
}
Expand Down Expand Up @@ -233,6 +243,8 @@ void ScreenManager::shutdown() {
for (auto layer : nextStack_)
delete layer.screen;
nextStack_.clear();
delete overlayScreen_;
overlayScreen_ = nullptr;
}

void ScreenManager::push(Screen *screen, int layerFlags) {
Expand Down Expand Up @@ -325,3 +337,11 @@ void ScreenManager::processFinishDialog() {
dialogFinished_ = nullptr;
}
}

void ScreenManager::SetOverlayScreen(Screen *screen) {
if (overlayScreen_) {
delete overlayScreen_;
}
overlayScreen_ = screen;
overlayScreen_->setScreenManager(this);
}
9 changes: 7 additions & 2 deletions Common/UI/Screen.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ class ScreenManager {

void getFocusPosition(float &x, float &y, float &z);

// Will delete any existing overlay screen.
void SetOverlayScreen(Screen *screen);

std::recursive_mutex inputLock_;

private:
Expand All @@ -157,8 +160,10 @@ class ScreenManager {
PostRenderCallback postRenderCb_ = nullptr;
void *postRenderUserdata_ = nullptr;

const Screen *dialogFinished_;
DialogResult dialogResult_;
const Screen *dialogFinished_ = nullptr;
DialogResult dialogResult_{};

Screen *overlayScreen_ = nullptr;

struct Layer {
Screen *screen;
Expand Down
2 changes: 1 addition & 1 deletion Core/CwCheat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ void CWCheatEngine::CreateCheatFile() {
}
if (!File::Exists(filename_)) {
auto err = GetI18NCategory(I18NCat::ERRORS);
System_NotifyUserMessage(err->T("Unable to create cheat file, disk may be full"));
g_OSD.Show(OSDType::MESSAGE_ERROR, err->T("Unable to create cheat file, disk may be full"));
}
}
}
Expand Down
12 changes: 6 additions & 6 deletions Core/Dialog/SavedataParam.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ int SavedataParam::Save(SceUtilitySavedataParam* param, const std::string &saveD
if (!pspFileSystem.GetFileInfo(dirPath).exists) {
if (!pspFileSystem.MkDir(dirPath)) {
auto err = GetI18NCategory(I18NCat::ERRORS);
System_NotifyUserMessage(err->T("Unable to write savedata, disk may be full"));
g_OSD.Show(OSDType::MESSAGE_ERROR, err->T("Unable to write savedata, disk may be full"));
}
}

Expand Down Expand Up @@ -485,7 +485,7 @@ int SavedataParam::Save(SceUtilitySavedataParam* param, const std::string &saveD

if (EncryptData(decryptMode, cryptedData, &cryptedSize, &aligned_len, cryptedHash, (hasKey ? param->key : 0)) != 0) {
auto err = GetI18NCategory(I18NCat::ERRORS);
System_NotifyUserMessage(err->T("Save encryption failed. This save won't work on real PSP"), 6.0f);
g_OSD.Show(OSDType::MESSAGE_WARNING, err->T("Save encryption failed. This save won't work on real PSP"), 6.0f);
ERROR_LOG(SCEUTILITY,"Save encryption failed. This save won't work on real PSP");
delete[] cryptedData;
cryptedData = 0;
Expand Down Expand Up @@ -775,8 +775,8 @@ u32 SavedataParam::LoadCryptedSave(SceUtilitySavedataParam *param, u8 *data, con
// Don't notify the user if we're not going to upgrade the save.
if (!g_Config.bEncryptSave) {
auto di = GetI18NCategory(I18NCat::DIALOG);
System_NotifyUserMessage(di->T("When you save, it will load on a PSP, but not an older PPSSPP"), 6.0f);
System_NotifyUserMessage(di->T("Old savedata detected"), 6.0f);
g_OSD.Show(OSDType::MESSAGE_WARNING, di->T("When you save, it will load on a PSP, but not an older PPSSPP"), 6.0f);
g_OSD.Show(OSDType::MESSAGE_WARNING, di->T("Old savedata detected"), 6.0f);
}
} else {
if (decryptMode == 5 && prevCryptMode == 3) {
Expand All @@ -787,8 +787,8 @@ u32 SavedataParam::LoadCryptedSave(SceUtilitySavedataParam *param, u8 *data, con
if (g_Config.bSavedataUpgrade) {
decryptMode = prevCryptMode;
auto di = GetI18NCategory(I18NCat::DIALOG);
System_NotifyUserMessage(di->T("When you save, it will not work on outdated PSP Firmware anymore"), 6.0f);
System_NotifyUserMessage(di->T("Old savedata detected"), 6.0f);
g_OSD.Show(OSDType::MESSAGE_WARNING, di->T("When you save, it will not work on outdated PSP Firmware anymore"), 6.0f);
g_OSD.Show(OSDType::MESSAGE_WARNING, di->T("Old savedata detected"), 6.0f);
}
}
hasKey = decryptMode > 1;
Expand Down
2 changes: 1 addition & 1 deletion Core/FileSystems/BlockDevices.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ u32 BlockDevice::CalculateCRC(volatile bool *cancel) {
void BlockDevice::NotifyReadError() {
auto err = GetI18NCategory(I18NCat::ERRORS);
if (!reportedError_) {
System_NotifyUserMessage(err->T("Game disc read error - ISO corrupt"), 6.0f);
g_OSD.Show(OSDType::MESSAGE_ERROR, err->T("Game disc read error - ISO corrupt"), 6.0f);
reportedError_ = true;
}
}
Expand Down
6 changes: 3 additions & 3 deletions Core/FileSystems/DirectoryFileSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ bool DirectoryFileHandle::Open(const Path &basePath, std::string &fileName, File
if (w32err == ERROR_DISK_FULL || w32err == ERROR_NOT_ENOUGH_QUOTA) {
// This is returned when the disk is full.
auto err = GetI18NCategory(I18NCat::ERRORS);
System_NotifyUserMessage(err->T("Disk full while writing data"));
g_OSD.Show(OSDType::MESSAGE_ERROR, err->T("Disk full while writing data"));
error = SCE_KERNEL_ERROR_ERRNO_NO_PERM;
} else if (!success) {
error = SCE_KERNEL_ERROR_ERRNO_FILE_NOT_FOUND;
Expand Down Expand Up @@ -290,7 +290,7 @@ bool DirectoryFileHandle::Open(const Path &basePath, std::string &fileName, File
} else if (errno == ENOSPC) {
// This is returned when the disk is full.
auto err = GetI18NCategory(I18NCat::ERRORS);
System_NotifyUserMessage(err->T("Disk full while writing data"));
g_OSD.Show(OSDType::MESSAGE_ERROR, err->T("Disk full while writing data"));
error = SCE_KERNEL_ERROR_ERRNO_NO_PERM;
} else {
error = SCE_KERNEL_ERROR_ERRNO_FILE_NOT_FOUND;
Expand Down Expand Up @@ -365,7 +365,7 @@ size_t DirectoryFileHandle::Write(const u8* pointer, s64 size)
if (diskFull) {
ERROR_LOG(FILESYS, "Disk full");
auto err = GetI18NCategory(I18NCat::ERRORS);
System_NotifyUserMessage(err->T("Disk full while writing data"));
g_OSD.Show(OSDType::MESSAGE_ERROR, err->T("Disk full while writing data"));
// We only return an error when the disk is actually full.
// When writing this would cause the disk to be full, so it wasn't written, we return 0.
if (MemoryStick_FreeSpace() == 0) {
Expand Down
13 changes: 6 additions & 7 deletions Core/HLE/proAdhoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1385,7 +1385,7 @@ int friendFinder(){
g_adhocServerIP.in.sin_addr.s_addr = INADDR_NONE;
if (g_Config.bEnableWlan && !net::DNSResolve(g_Config.proAdhocServer, "", &resolved, err)) {
ERROR_LOG(SCENET, "DNS Error Resolving %s\n", g_Config.proAdhocServer.c_str());
System_NotifyUserMessage(n->T("DNS Error Resolving ") + g_Config.proAdhocServer, 2.0f, 0x0000ff);
g_OSD.Show(OSDType::MESSAGE_ERROR, n->T("DNS Error Resolving ") + g_Config.proAdhocServer);
}
if (resolved) {
for (auto ptr = resolved; ptr != NULL; ptr = ptr->ai_next) {
Expand Down Expand Up @@ -1447,7 +1447,7 @@ int friendFinder(){
shutdown((int)metasocket, SD_BOTH);
closesocket((int)metasocket);
metasocket = (int)INVALID_SOCKET;
System_NotifyUserMessage(std::string(n->T("Disconnected from AdhocServer")) + " (" + std::string(n->T("Error")) + ": " + std::to_string(error) + ")", 2.0, 0x0000ff);
g_OSD.Show(OSDType::MESSAGE_ERROR, std::string(n->T("Disconnected from AdhocServer")) + " (" + std::string(n->T("Error")) + ": " + std::to_string(error) + ")");
// Mark all friends as timedout since we won't be able to detects disconnected friends anymore without being connected to Adhoc Server
peerlock.lock();
timeoutFriendsRecursive(friends);
Expand Down Expand Up @@ -2191,7 +2191,7 @@ int initNetwork(SceNetAdhocctlAdhocId *adhoc_id){
iResult = bind((int)metasocket, &g_localhostIP.addr, sizeof(g_localhostIP.addr));
if (iResult == SOCKET_ERROR) {
ERROR_LOG(SCENET, "Bind to alternate localhost[%s] failed(%i).", ip2str(g_localhostIP.in.sin_addr).c_str(), iResult);
System_NotifyUserMessage(std::string(n->T("Failed to Bind Localhost IP")) + " " + ip2str(g_localhostIP.in.sin_addr).c_str(), 2.0, 0x0000ff);
g_OSD.Show(OSDType::MESSAGE_ERROR, std::string(n->T("Failed to Bind Localhost IP")) + " " + ip2str(g_localhostIP.in.sin_addr).c_str());
}
}

Expand Down Expand Up @@ -2246,7 +2246,7 @@ int initNetwork(SceNetAdhocctlAdhocId *adhoc_id){
}
if (!done) {
ERROR_LOG(SCENET, "Socket error (%i) when connecting to AdhocServer [%s/%s:%u]", errorcode, g_Config.proAdhocServer.c_str(), ip2str(g_adhocServerIP.in.sin_addr).c_str(), ntohs(g_adhocServerIP.in.sin_port));
System_NotifyUserMessage(std::string(n->T("Failed to connect to Adhoc Server")) + " (" + std::string(n->T("Error")) + ": " + std::to_string(errorcode) + ")", 1.0f, 0x0000ff);
g_OSD.Show(OSDType::MESSAGE_ERROR, std::string(n->T("Failed to connect to Adhoc Server")) + " (" + std::string(n->T("Error")) + ": " + std::to_string(errorcode) + ")");
return iResult;
}
}
Expand All @@ -2268,10 +2268,9 @@ int initNetwork(SceNetAdhocctlAdhocId *adhoc_id){
socklen_t addrLen = sizeof(LocalIP);
memset(&LocalIP, 0, addrLen);
getsockname((int)metasocket, &LocalIP, &addrLen);
System_NotifyUserMessage(n->T("Network Initialized"), 1.0);
g_OSD.Show(OSDType::MESSAGE_SUCCESS, n->T("Network Initialized"), 1.0);
return 0;
}
else{
} else {
return SOCKET_ERROR;
}
}
Expand Down
2 changes: 1 addition & 1 deletion Core/HLE/proAdhocServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1858,7 +1858,7 @@ int create_listen_socket(uint16_t port)
else {
ERROR_LOG(SCENET, "AdhocServer: Bind returned %i (Socket error %d)", bindresult, errno);
auto n = GetI18NCategory(I18NCat::NETWORKING);
System_NotifyUserMessage(std::string(n->T("AdhocServer Failed to Bind Port")) + " " + std::to_string(port), 3.0, 0x0000ff);
g_OSD.Show(OSDType::MESSAGE_ERROR, std::string(n->T("AdhocServer Failed to Bind Port")) + " " + std::to_string(port));
}

// Close Socket
Expand Down
4 changes: 2 additions & 2 deletions Core/HLE/sceDisplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -576,9 +576,9 @@ void __DisplayFlip(int cyclesLate) {
#ifndef _DEBUG
auto err = GetI18NCategory(I18NCat::ERRORS);
if (g_Config.bSoftwareRendering) {
System_NotifyUserMessage(err->T("Running slow: Try turning off Software Rendering"), 6.0f, 0xFF30D0D0);
g_OSD.Show(OSDType::MESSAGE_INFO, err->T("Running slow: Try turning off Software Rendering"));
} else {
System_NotifyUserMessage(err->T("Running slow: try frameskip, sound is choppy when slow"), 6.0f, 0xFF30D0D0);
g_OSD.Show(OSDType::MESSAGE_INFO, err->T("Running slow: try frameskip, sound is choppy when slow"));
}
#endif
hasNotifiedSlow = true;
Expand Down
Loading

0 comments on commit 9df01a5

Please sign in to comment.