Implement an "OverlayScreen" concept. OSD can now render on top of other screens than EmuScreen.

This commit is contained in:
Henrik Rydgård 2023-06-19 15:50:36 +02:00
parent 56e5cbee91
commit d6552a7673
7 changed files with 71 additions and 27 deletions

View file

@ -53,6 +53,10 @@ void ScreenManager::update() {
stack_.back().screen->update();
}
if (overlayScreen_) {
overlayScreen_->update();
}
g_iconCache.FrameUpdate();
}
@ -174,6 +178,9 @@ void ScreenManager::render() {
stack_.back().screen->render();
if (postRenderCb_)
postRenderCb_(getUIContext(), postRenderUserdata_);
if (overlayScreen_) {
overlayScreen_->render();
}
backback.screen->postRender();
break;
}
@ -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;
}
@ -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) {
@ -325,3 +337,11 @@ void ScreenManager::processFinishDialog() {
dialogFinished_ = nullptr;
}
}
void ScreenManager::SetOverlayScreen(Screen *screen) {
if (overlayScreen_) {
delete overlayScreen_;
}
overlayScreen_ = screen;
overlayScreen_->setScreenManager(this);
}

View file

@ -144,6 +144,9 @@ public:
void getFocusPosition(float &x, float &y, float &z);
// Will delete any existing overlay screen.
void SetOverlayScreen(Screen *screen);
std::recursive_mutex inputLock_;
private:
@ -157,8 +160,10 @@ private:
PostRenderCallback postRenderCb_ = nullptr;
void *postRenderUserdata_ = nullptr;
const Screen *dialogFinished_;
DialogResult dialogResult_;
const Screen *dialogFinished_ = nullptr;
DialogResult dialogResult_{};
Screen *overlayScreen_ = nullptr;
struct Layer {
Screen *screen;

View file

@ -936,7 +936,6 @@ void EmuScreen::CreateViews() {
saveStatePreview_->SetVisibility(V_GONE);
saveStatePreview_->SetCanBeFocused(false);
root_->Add(saveStatePreview_);
onScreenMessagesView_ = root_->Add(new OnScreenMessagesView(new AnchorLayoutParams((Size)bounds.w, (Size)bounds.h)));
GameInfoBGView *loadingBG = root_->Add(new GameInfoBGView(gamePath_, new AnchorLayoutParams(FILL_PARENT, FILL_PARENT)));
TextView *loadingTextView = root_->Add(new TextView(sc->T(PSP_GetLoading()), new AnchorLayoutParams(bounds.centerX(), NONE, NONE, 40, true)));
@ -1042,7 +1041,6 @@ void EmuScreen::update() {
using namespace UI;
UIScreen::update();
onScreenMessagesView_->SetVisibility(g_Config.bShowOnScreenMessages ? V_VISIBLE : V_GONE);
resumeButton_->SetVisibility(coreState == CoreState::CORE_RUNTIME_ERROR && Memory::MemFault_MayBeResumable() ? V_VISIBLE : V_GONE);
resetButton_->SetVisibility(coreState == CoreState::CORE_RUNTIME_ERROR ? V_VISIBLE : V_GONE);

View file

@ -32,7 +32,6 @@
struct AxisInput;
class AsyncImageFileView;
class OnScreenMessagesView;
class ChatMenu;
class EmuScreen : public UIScreen {
@ -113,7 +112,6 @@ private:
ChatMenu *chatMenu_ = nullptr;
UI::Button *cardboardDisableButton_ = nullptr;
OnScreenMessagesView *onScreenMessagesView_ = nullptr;
ControlMapper controlMapper_;
};

View file

@ -786,6 +786,8 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch
g_screenManager->switchScreen(new LogoScreen(AfterLogoScreen::DEFAULT));
}
g_screenManager->SetOverlayScreen(new OSDOverlayScreen());
// Easy testing
// screenManager->push(new GPUDriverTestScreen());
@ -1016,27 +1018,6 @@ void TakeScreenshot() {
}
void RenderOverlays(UIContext *dc, void *userdata) {
// Thin bar at the top of the screen.
std::vector<float> progress = g_DownloadManager.GetCurrentProgress();
if (!progress.empty()) {
static const uint32_t colors[4] = {
0xFFFFFFFF,
0xFFCCCCCC,
0xFFAAAAAA,
0xFF777777,
};
dc->Begin();
int h = 5;
for (size_t i = 0; i < progress.size(); i++) {
float barWidth = 10 + (dc->GetBounds().w - 10) * progress[i];
Bounds bounds(0, h * i, barWidth, h);
UI::Drawable solid(colors[i & 3]);
dc->FillRect(solid, bounds);
}
dc->Flush();
}
if (g_TakeScreenshot) {
TakeScreenshot();
}

View file

@ -10,10 +10,16 @@
#include "Common/UI/Context.h"
#include "Common/TimeUtil.h"
#include "Common/Net/HTTPClient.h"
#include "Core/Config.h"
OnScreenMessages osm;
void OnScreenMessagesView::Draw(UIContext &dc) {
if (!g_Config.bShowOnScreenMessages) {
return;
}
// First, clean out old messages.
osm.Lock();
osm.Clean();
@ -61,6 +67,27 @@ void OnScreenMessagesView::Draw(UIContext &dc) {
}
osm.Unlock();
// Thin bar at the top of the screen.
std::vector<float> progress = g_DownloadManager.GetCurrentProgress();
if (!progress.empty()) {
static const uint32_t colors[4] = {
0xFFFFFFFF,
0xFFCCCCCC,
0xFFAAAAAA,
0xFF777777,
};
dc.Begin();
int h = 5;
for (size_t i = 0; i < progress.size(); i++) {
float barWidth = 10 + (dc.GetBounds().w - 10) * progress[i];
Bounds bounds(0, h * i, barWidth, h);
UI::Drawable solid(colors[i & 3]);
dc.FillRect(solid, bounds);
}
dc.Flush();
}
}
std::string OnScreenMessagesView::DescribeText() const {
@ -114,3 +141,8 @@ void OnScreenMessages::Show(const std::string &text, float duration_s, uint32_t
void OnScreenMessages::ShowOnOff(const std::string &message, bool b, float duration_s, uint32_t color, int icon) {
Show(message + (b ? ": on" : ": off"), duration_s, color, icon);
}
void OSDOverlayScreen::CreateViews() {
root_ = new UI::AnchorLayout();
root_->Add(new OnScreenMessagesView(new UI::AnchorLayoutParams(0.0f, 0.0f, 0.0f, 0.0f)));
}

View file

@ -6,9 +6,11 @@
#include "Common/Math/geom2d.h"
#include "Common/UI/View.h"
#include "Common/UI/UIScreen.h"
class DrawBuffer;
// Data holder. This one is currently global.
class OnScreenMessages {
public:
void Show(const std::string &message, float duration_s = 1.0f, uint32_t color = 0xFFFFFF, int icon = -1, bool checkUnique = true, const char *id = nullptr);
@ -39,6 +41,8 @@ private:
std::mutex mutex_;
};
// Infrastructure for rendering overlays.
class OnScreenMessagesView : public UI::InertView {
public:
OnScreenMessagesView(UI::LayoutParams *layoutParams = nullptr) : UI::InertView(layoutParams) {}
@ -46,4 +50,10 @@ public:
std::string DescribeText() const override;
};
class OSDOverlayScreen : public UIScreen {
public:
const char *tag() const override { return "OSDOverlayScreen"; }
void CreateViews() override;
};
extern OnScreenMessages osm;