mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-12 22:10:29 +02:00
Show a tiny indicator in the top left of the screen when the game is saving or loading.
This commit is contained in:
1 parent
028392233c
commit
f410b7e6ea
8 files changed
+65
-24
No files matched your search
+10
-1
@@ -69,7 +69,7 @@ void OnScreenDisplay::ClickEntry(size_t index, double now) {
|
||||
}
|
||||
|
||||
void OnScreenDisplay::Show(OSDType type, std::string_view text, std::string_view text2, std::string_view icon, float duration_s, const char *id) {
|
||||
if (text.empty()) {
|
||||
if (text.empty() && type != OSDType::STATUS_ICON) {
|
||||
// The user hacked the translation files to get rid of the message. Let's reward the dedication
|
||||
// by skipping it entirely.
|
||||
return;
|
||||
@@ -335,3 +335,12 @@ void OnScreenDisplay::SetClickCallback(const char *id, void (*callback)(bool, vo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnScreenDisplay::SetFlags(const char *id, OSDMessageFlags flags) {
|
||||
for (auto &ent : entries_) {
|
||||
// protect against dupes.
|
||||
if (ent.id == id) {
|
||||
ent.flags = flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
+15
-1
@@ -5,6 +5,8 @@
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
|
||||
#include "Common/Common.h"
|
||||
|
||||
// Shows a visible message to the user.
|
||||
// The default implementation in NativeApp.cpp uses our "osm" system (on screen messaging).
|
||||
enum class OSDType {
|
||||
@@ -29,11 +31,21 @@ enum class OSDType {
|
||||
|
||||
PROGRESS_BAR,
|
||||
|
||||
TRANSPARENT_STATUS, // Use icons from the atlas
|
||||
STATUS_ICON, // Use icons from the atlas
|
||||
|
||||
VALUE_COUNT,
|
||||
};
|
||||
|
||||
#undef None // X11, sigh.
|
||||
|
||||
enum class OSDMessageFlags {
|
||||
None = 0,
|
||||
SpinLeft = 1,
|
||||
SpinRight = 2,
|
||||
Transparent = 4,
|
||||
};
|
||||
ENUM_CLASS_BITOPS(OSDMessageFlags);
|
||||
|
||||
// Data holder for on-screen messages.
|
||||
class OnScreenDisplay {
|
||||
public:
|
||||
@@ -78,6 +90,7 @@ public:
|
||||
|
||||
// Can't add an infinite number of "Show" functions, so starting to offer post-modification.
|
||||
void SetClickCallback(const char *id, void (*callback)(bool, void *), void *userdata);
|
||||
void SetFlags(const char *id, OSDMessageFlags flag);
|
||||
|
||||
struct Entry {
|
||||
OSDType type;
|
||||
@@ -86,6 +99,7 @@ public:
|
||||
std::string iconName;
|
||||
int numericID;
|
||||
std::string id;
|
||||
OSDMessageFlags flags;
|
||||
|
||||
// We could use std::function, but prefer to do it the oldschool way.
|
||||
void (*clickCallback)(bool, void *);
|
||||
|
||||
@@ -352,6 +352,11 @@ void UIContext::DrawImageVGradient(ImageID image, uint32_t color1, uint32_t colo
|
||||
uidrawbuffer_->DrawImageStretchVGradient(image, bounds.x, bounds.y, bounds.x2(), bounds.y2(), color1, color2);
|
||||
}
|
||||
|
||||
void UIContext::DrawImageRotated(ImageID atlas_image, float x, float y, float scale, float angle, uint32_t color, bool mirror_h) {
|
||||
uidrawbuffer_->DrawImageRotated(atlas_image, x, y, scale, angle, color, mirror_h);
|
||||
}
|
||||
|
||||
|
||||
void UIContext::PushTransform(const UITransform &transform) {
|
||||
Flush();
|
||||
|
||||
|
||||
@@ -95,6 +95,7 @@ public:
|
||||
void FillRect(const UI::Drawable &drawable, const Bounds &bounds);
|
||||
void DrawRectDropShadow(const Bounds &bounds, float radius, float alpha, uint32_t color = 0);
|
||||
void DrawImageVGradient(ImageID image, uint32_t color1, uint32_t color2, const Bounds &bounds);
|
||||
void DrawImageRotated(ImageID atlas_image, float x, float y, float scale, float angle, uint32_t color, bool mirror_h);
|
||||
|
||||
// in dps, like dp_xres and dp_yres
|
||||
void SetBounds(const Bounds &b) { bounds_ = b; }
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "Common/Data/Encoding/Utf8.h"
|
||||
#include "Common/Data/Text/I18n.h"
|
||||
#include "Common/System/OSD.h"
|
||||
#include "Common/File/FileUtil.h"
|
||||
#include "Common/Serialize/Serializer.h"
|
||||
#include "Common/Serialize/SerializeFuncs.h"
|
||||
@@ -1095,6 +1096,7 @@ int PSPSaveDialog::Update(int animSpeed)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// It's kinda ugly how this uses the "global" 'display'...
|
||||
void PSPSaveDialog::ExecuteIOAction() {
|
||||
param.ClearSFOCache();
|
||||
auto &result = param.GetPspParam()->common.result;
|
||||
@@ -1229,21 +1231,26 @@ void PSPSaveDialog::ExecuteNotVisibleIOAction() {
|
||||
param.ClearSFOCache();
|
||||
}
|
||||
|
||||
static void DoExecuteIOAction(PSPSaveDialog *dialog) {
|
||||
SetCurrentThreadName("SaveIO");
|
||||
|
||||
AndroidJNIThreadContext jniContext;
|
||||
dialog->ExecuteIOAction();
|
||||
}
|
||||
|
||||
void PSPSaveDialog::StartIOThread() {
|
||||
if (ioThread.joinable()) {
|
||||
WARN_LOG_REPORT(Log::sceUtility, "Starting a save io thread when one already pending, uh oh.");
|
||||
ioThread.join();
|
||||
}
|
||||
|
||||
// Show save indicator. It's strange how "display" is just as much an action as what to display.
|
||||
if (display == DS_SAVE_SAVING || display == DS_LOAD_LOADING || display == DS_DELETE_DELETING) {
|
||||
const bool left = display == DS_LOAD_LOADING;
|
||||
g_OSD.Show(OSDType::STATUS_ICON, "", "", left ? "I_ROTATE_LEFT" : "I_ROTATE_RIGHT", 1.0f, "save_indicator");
|
||||
g_OSD.SetFlags("save_indicator", (left ? OSDMessageFlags::SpinLeft : OSDMessageFlags::SpinRight) | OSDMessageFlags::Transparent);
|
||||
}
|
||||
|
||||
ioThreadStatus = SAVEIO_PENDING;
|
||||
ioThread = std::thread(&DoExecuteIOAction, this);
|
||||
ioThread = std::thread([this]() {
|
||||
SetCurrentThreadName("SaveIO");
|
||||
|
||||
AndroidJNIThreadContext jniContext;
|
||||
this->ExecuteIOAction();
|
||||
});
|
||||
}
|
||||
|
||||
int PSPSaveDialog::Shutdown(bool force) {
|
||||
|
||||
@@ -58,8 +58,7 @@ namespace
|
||||
|
||||
void SetStringFromSFO(ParamSFOData &sfoFile, const char *name, char *str, int strLength)
|
||||
{
|
||||
std::string value = sfoFile.GetValueString(name);
|
||||
truncate_cpy(str, strLength, value.c_str());
|
||||
truncate_cpy(str, strLength, sfoFile.GetValueString(name));
|
||||
}
|
||||
|
||||
bool ReadPSPFile(const std::string &filename, u8 **data, s64 dataSize, s64 *readSize)
|
||||
@@ -79,7 +78,7 @@ namespace
|
||||
|
||||
size_t result = pspFileSystem.ReadFile(handle, *data, dataSize);
|
||||
pspFileSystem.CloseFile(handle);
|
||||
if(readSize)
|
||||
if (readSize)
|
||||
*readSize = result;
|
||||
|
||||
return result != 0;
|
||||
|
||||
+2
-1
@@ -713,7 +713,8 @@ static void ShowFpsLimitNotice() {
|
||||
|
||||
char temp[51];
|
||||
snprintf(temp, sizeof(temp), "%d%%", (int)((float)fpsLimit / 60.0f * 100.0f));
|
||||
g_OSD.Show(OSDType::TRANSPARENT_STATUS, temp, "", "I_FASTFORWARD", 1.5f, "altspeed");
|
||||
g_OSD.Show(OSDType::STATUS_ICON, temp, "", "I_FASTFORWARD", 1.5f, "altspeed");
|
||||
g_OSD.SetFlags("altspeed", OSDMessageFlags::Transparent);
|
||||
}
|
||||
|
||||
void EmuScreen::onVKey(VirtKey virtualKeyCode, bool down) {
|
||||
|
||||
+15
-10
@@ -118,12 +118,12 @@ static void MeasureOSDEntry(const UIContext &dc, const OnScreenDisplay::Entry &e
|
||||
}
|
||||
}
|
||||
|
||||
static void RenderNotice(UIContext &dc, Bounds bounds, float height1, NoticeLevel level, const std::string &text, const std::string &details, const std::string &iconName, int align, float alpha, bool transparent) {
|
||||
static void RenderNotice(UIContext &dc, Bounds bounds, float height1, NoticeLevel level, const std::string &text, const std::string &details, const std::string &iconName, int align, float alpha, OSDMessageFlags flags, float timeVal) {
|
||||
UI::Drawable background = UI::Drawable(colorAlpha(GetNoticeBackgroundColor(level), alpha));
|
||||
|
||||
uint32_t foreGround = whiteAlpha(alpha);
|
||||
|
||||
if (!transparent) {
|
||||
if (!(flags & OSDMessageFlags::Transparent)) {
|
||||
dc.DrawRectDropShadow(bounds, 12.0f, 0.7f * alpha);
|
||||
dc.FillRect(background, bounds);
|
||||
}
|
||||
@@ -153,7 +153,13 @@ static void RenderNotice(UIContext &dc, Bounds bounds, float height1, NoticeLeve
|
||||
// easily melts into the orange of warnings otherwise.
|
||||
dc.FillRect(UI::Drawable(0x50000000), iconBounds.Expand(2.0f));
|
||||
}
|
||||
dc.DrawImageVGradient(iconID, foreGround, foreGround, Bounds(bounds.x + 2.5f, bounds.y + 2.5f, iconW, iconH));
|
||||
|
||||
if (flags & (OSDMessageFlags::SpinLeft | OSDMessageFlags::SpinRight)) {
|
||||
const float direction = (flags & OSDMessageFlags::SpinLeft) ? -1.5f : 1.5f;
|
||||
dc.DrawImageRotated(iconID, bounds.x + 2.5f + iconW * 0.5f, bounds.y + 2.5f + iconW * 0.5f, 1.0f, direction * time_now_d(), foreGround, false);
|
||||
} else {
|
||||
dc.DrawImageVGradient(iconID, foreGround, foreGround, Bounds(bounds.x + 2.5f, bounds.y + 2.5f, iconW, iconH));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,7 +174,7 @@ static void RenderNotice(UIContext &dc, Bounds bounds, float height1, NoticeLeve
|
||||
|
||||
if (!details.empty()) {
|
||||
Bounds bottomTextBounds = bounds.Inset(3.0f, height1 + 5.0f, 3.0f, 3.0f);
|
||||
if (!transparent) {
|
||||
if (!(flags & OSDMessageFlags::Transparent)) {
|
||||
UI::Drawable backgroundDark = UI::Drawable(colorAlpha(darkenColor(GetNoticeBackgroundColor(level)), alpha));
|
||||
dc.FillRect(backgroundDark, bottomTextBounds);
|
||||
}
|
||||
@@ -178,7 +184,7 @@ static void RenderNotice(UIContext &dc, Bounds bounds, float height1, NoticeLeve
|
||||
dc.SetFontScale(1.0f, 1.0f);
|
||||
}
|
||||
|
||||
static void RenderOSDEntry(UIContext &dc, const OnScreenDisplay::Entry &entry, Bounds bounds, float height1, int align, float alpha) {
|
||||
static void RenderOSDEntry(UIContext &dc, const OnScreenDisplay::Entry &entry, Bounds bounds, float height1, int align, float alpha, float now) {
|
||||
if (entry.type == OSDType::ACHIEVEMENT_UNLOCKED) {
|
||||
const rc_client_achievement_t * achievement = rc_client_get_achievement_info(Achievements::GetClient(), entry.numericID);
|
||||
if (achievement) {
|
||||
@@ -186,8 +192,7 @@ static void RenderOSDEntry(UIContext &dc, const OnScreenDisplay::Entry &entry, B
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
bool transparent = entry.type == OSDType::TRANSPARENT_STATUS;
|
||||
RenderNotice(dc, bounds, height1, GetNoticeLevel(entry.type), entry.text, entry.text2, entry.iconName, align, alpha, transparent);
|
||||
RenderNotice(dc, bounds, height1, GetNoticeLevel(entry.type), entry.text, entry.text2, entry.iconName, align, alpha, entry.flags, now - entry.startTime);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,7 +314,7 @@ void OnScreenMessagesView::Draw(UIContext &dc) {
|
||||
typeEdges[(size_t)OSDType::ACHIEVEMENT_UNLOCKED] = (ScreenEdgePosition)g_Config.iAchievementsUnlockedPos;
|
||||
typeEdges[(size_t)OSDType::MESSAGE_CENTERED_WARNING] = ScreenEdgePosition::CENTER;
|
||||
typeEdges[(size_t)OSDType::MESSAGE_CENTERED_ERROR] = ScreenEdgePosition::CENTER;
|
||||
typeEdges[(size_t)OSDType::TRANSPARENT_STATUS] = ScreenEdgePosition::TOP_LEFT;
|
||||
typeEdges[(size_t)OSDType::STATUS_ICON] = ScreenEdgePosition::TOP_LEFT;
|
||||
typeEdges[(size_t)OSDType::PROGRESS_BAR] = ScreenEdgePosition::TOP_CENTER; // These only function at the top currently, needs fixing.
|
||||
|
||||
dc.SetFontStyle(dc.theme->uiFont);
|
||||
@@ -471,7 +476,7 @@ void OnScreenMessagesView::Draw(UIContext &dc) {
|
||||
}
|
||||
|
||||
float alpha = Clamp((float)(entry.endTime - now) * 4.0f, 0.0f, 1.0f);
|
||||
RenderOSDEntry(dc, entry, b, measuredEntry.h1, measuredEntry.align, alpha);
|
||||
RenderOSDEntry(dc, entry, b, measuredEntry.h1, measuredEntry.align, alpha, now);
|
||||
|
||||
switch (entry.type) {
|
||||
case OSDType::MESSAGE_INFO:
|
||||
@@ -584,6 +589,6 @@ void NoticeView::GetContentDimensionsBySpec(const UIContext &dc, UI::MeasureSpec
|
||||
|
||||
void NoticeView::Draw(UIContext &dc) {
|
||||
dc.PushScissor(bounds_);
|
||||
RenderNotice(dc, bounds_, height1_, level_, text_, detailsText_, iconName_, 0, 1.0f, false);
|
||||
RenderNotice(dc, bounds_, height1_, level_, text_, detailsText_, iconName_, 0, 1.0f, OSDMessageFlags::None, 0.0f);
|
||||
dc.PopScissor();
|
||||
}
|
||||
Reference in new issue
Block a user