achievements: leaderboard notifications. detailed toast message
Draw achievement notifications using imgui drawlist api Fixes for insets Issue #761
This commit is contained in:
parent
763d9ce06a
commit
f76d05a3d5
|
@ -89,6 +89,12 @@ private:
|
|||
void handleShowAchievementProgress(const rc_client_event_t *event);
|
||||
void handleHideAchievementProgress(const rc_client_event_t *event);
|
||||
void handleUpdateAchievementProgress(const rc_client_event_t *event);
|
||||
void handleLeaderboardStarted(const rc_client_event_t *event);
|
||||
void handleLeaderboardFailed(const rc_client_event_t *event);
|
||||
void handleLeaderboardSubmitted(const rc_client_event_t *event);
|
||||
void handleShowLeaderboardTracker(const rc_client_event_t *event);
|
||||
void handleHideLeaderboardTracker(const rc_client_event_t *event);
|
||||
void handleUpdateLeaderboardTracker(const rc_client_event_t *event);
|
||||
static void emuEventCallback(Event event, void *arg);
|
||||
|
||||
rc_client_t *rc_client = nullptr;
|
||||
|
@ -506,16 +512,26 @@ void Achievements::clientEventHandler(const rc_client_event_t* event, rc_client_
|
|||
achievements->handleUpdateAchievementProgress(event);
|
||||
break;
|
||||
|
||||
/*
|
||||
TODO
|
||||
case RC_CLIENT_EVENT_LEADERBOARD_STARTED:
|
||||
achievements->handleLeaderboardStarted(event);
|
||||
break;
|
||||
case RC_CLIENT_EVENT_LEADERBOARD_FAILED:
|
||||
achievements->handleLeaderboardFailed(event);
|
||||
break;
|
||||
case RC_CLIENT_EVENT_LEADERBOARD_SUBMITTED:
|
||||
case RC_CLIENT_EVENT_LEADERBOARD_SCOREBOARD:
|
||||
achievements->handleLeaderboardSubmitted(event);
|
||||
break;
|
||||
case RC_CLIENT_EVENT_LEADERBOARD_TRACKER_SHOW:
|
||||
achievements->handleShowLeaderboardTracker(event);
|
||||
break;
|
||||
case RC_CLIENT_EVENT_LEADERBOARD_TRACKER_HIDE:
|
||||
achievements->handleHideLeaderboardTracker(event);
|
||||
break;
|
||||
case RC_CLIENT_EVENT_LEADERBOARD_TRACKER_UPDATE:
|
||||
*/
|
||||
achievements->handleUpdateLeaderboardTracker(event);
|
||||
break;
|
||||
// TODO case RC_CLIENT_EVENT_LEADERBOARD_SCOREBOARD:
|
||||
|
||||
case RC_CLIENT_EVENT_DISCONNECTED:
|
||||
notifyError("RetroAchievements disconnected");
|
||||
break;
|
||||
|
@ -578,6 +594,46 @@ void Achievements::handleAchievementChallengeIndicatorHideEvent(const rc_client_
|
|||
}
|
||||
}
|
||||
|
||||
void Achievements::handleLeaderboardStarted(const rc_client_event_t *event)
|
||||
{
|
||||
const rc_client_leaderboard_t *leaderboard = event->leaderboard;
|
||||
INFO_LOG(COMMON, "RA: Leaderboard started: %s", leaderboard->title);
|
||||
std::string text = "Leaderboard " + std::string(leaderboard->title) + " started";
|
||||
notifier.notify(Notification::Unlocked, "", text, leaderboard->description);
|
||||
}
|
||||
void Achievements::handleLeaderboardFailed(const rc_client_event_t *event)
|
||||
{
|
||||
const rc_client_leaderboard_t *leaderboard = event->leaderboard;
|
||||
INFO_LOG(COMMON, "RA: Leaderboard failed: %s", leaderboard->title);
|
||||
std::string text = "Leaderboard " + std::string(leaderboard->title) + " failed";
|
||||
notifier.notify(Notification::Unlocked, "", text, leaderboard->description);
|
||||
}
|
||||
void Achievements::handleLeaderboardSubmitted(const rc_client_event_t *event)
|
||||
{
|
||||
const rc_client_leaderboard_t *leaderboard = event->leaderboard;
|
||||
INFO_LOG(COMMON, "RA: Leaderboard submitted: %s", leaderboard->title);
|
||||
std::string text = "Leaderboard " + std::string(leaderboard->title) + " submitted";
|
||||
notifier.notify(Notification::Unlocked, "", text, leaderboard->description);
|
||||
}
|
||||
void Achievements::handleShowLeaderboardTracker(const rc_client_event_t *event)
|
||||
{
|
||||
const rc_client_leaderboard_tracker_t *leaderboard = event->leaderboard_tracker;
|
||||
DEBUG_LOG(COMMON, "RA: Show leaderboard[%d]: %s", leaderboard->id, leaderboard->display);
|
||||
notifier.showLeaderboard(leaderboard->id, leaderboard->display);
|
||||
}
|
||||
void Achievements::handleHideLeaderboardTracker(const rc_client_event_t *event)
|
||||
{
|
||||
const rc_client_leaderboard_tracker_t *leaderboard = event->leaderboard_tracker;
|
||||
DEBUG_LOG(COMMON, "RA: Hide leaderboard[%d]: %s", leaderboard->id, leaderboard->display);
|
||||
notifier.hideLeaderboard(leaderboard->id);
|
||||
}
|
||||
void Achievements::handleUpdateLeaderboardTracker(const rc_client_event_t *event)
|
||||
{
|
||||
const rc_client_leaderboard_tracker_t *leaderboard = event->leaderboard_tracker;
|
||||
DEBUG_LOG(COMMON, "RA: Update leaderboard[%d]: %s", leaderboard->id, leaderboard->display);
|
||||
notifier.showLeaderboard(leaderboard->id, leaderboard->display);
|
||||
}
|
||||
|
||||
void Achievements::handleGameCompleted(const rc_client_event_t *event)
|
||||
{
|
||||
const rc_client_game_t* game = rc_client_get_game_info(rc_client);
|
||||
|
|
|
@ -541,7 +541,7 @@ void Emulator::loadGame(const char *path, LoadProgress *progress)
|
|||
cheatManager.reset(settings.content.gameId);
|
||||
if (cheatManager.isWidescreen())
|
||||
{
|
||||
gui_display_notification("Widescreen cheat activated", 1000);
|
||||
gui_display_notification("Widescreen cheat activated", 2000);
|
||||
config::ScreenStretching.override(134); // 4:3 -> 16:9
|
||||
}
|
||||
// reload settings so that all settings can be overridden
|
||||
|
|
|
@ -830,8 +830,7 @@ private:
|
|||
std::string s = get_writable_data_path(settings.content.gameId + "-results.png");
|
||||
bitmapWriter->save(s);
|
||||
bitmapWriter.reset();
|
||||
s = "Print out saved to " + s;
|
||||
gui_display_notification(s.c_str(), 5000);
|
||||
gui_display_notification("Print out saved", 5000, s.c_str());
|
||||
NOTICE_LOG(NAOMI, "%s", s.c_str());
|
||||
}
|
||||
break;
|
||||
|
@ -1198,7 +1197,7 @@ std::string get_writable_data_path(const std::string& s)
|
|||
return "./" + s;
|
||||
}
|
||||
|
||||
void gui_display_notification(char const*, int) {
|
||||
void gui_display_notification(char const*, int, char const*) {
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
|
|
@ -2971,7 +2971,7 @@ static void gui_display_settings()
|
|||
ImGui::End();
|
||||
}
|
||||
|
||||
void gui_display_notification(const char *msg, int duration)
|
||||
void gui_display_notification(const char *msg, int duration, const char *details)
|
||||
{
|
||||
if (gui_state != GuiState::Closed)
|
||||
{
|
||||
|
@ -2980,7 +2980,7 @@ void gui_display_notification(const char *msg, int duration)
|
|||
osd_message_end = getTimeMs() + duration;
|
||||
}
|
||||
else {
|
||||
toast.show(msg, "", duration);
|
||||
toast.show(msg, details != nullptr ? details : "", duration);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3465,7 +3465,7 @@ void gui_display_osd()
|
|||
const ScaledVec2 padding(5.f, 5.f);
|
||||
const ImVec2 size = largeFont->CalcTextSizeA(largeFont->FontSize, FLT_MAX, maxW, &message.front(), &message.back() + 1)
|
||||
+ padding * 2.f;
|
||||
ImVec2 pos(0, ImGui::GetIO().DisplaySize.y - size.y);
|
||||
ImVec2 pos(insetLeft, ImGui::GetIO().DisplaySize.y - size.y);
|
||||
constexpr float alpha = 0.7f;
|
||||
const ImU32 bg_col = alphaOverride(0x00202020, alpha / 2.f);
|
||||
dl->AddRectFilled(pos, pos + size, bg_col, 0.f);
|
||||
|
@ -3560,7 +3560,7 @@ void fatal_error(const char* text, ...)
|
|||
va_end(args);
|
||||
ERROR_LOG(COMMON, "%s", temp);
|
||||
|
||||
gui_display_notification(temp, 2000);
|
||||
gui_display_notification("Fatal Error", 20000, temp);
|
||||
}
|
||||
|
||||
extern bool subfolders_read;
|
||||
|
|
|
@ -25,7 +25,7 @@ void gui_init();
|
|||
void gui_initFonts();
|
||||
void gui_open_settings();
|
||||
void gui_display_ui();
|
||||
void gui_display_notification(const char *msg, int duration);
|
||||
void gui_display_notification(const char *msg, int duration, const char *details = nullptr);
|
||||
void gui_display_osd();
|
||||
void gui_display_profiler();
|
||||
void gui_open_onboarding();
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <sstream>
|
||||
|
||||
extern ImFont *largeFont;
|
||||
extern int insetLeft;
|
||||
|
||||
namespace achievements
|
||||
{
|
||||
|
@ -42,6 +43,7 @@ static constexpr u64 NEVER_ENDS = 1000000000000;
|
|||
void Notification::notify(Type type, const std::string& image, const std::string& text1,
|
||||
const std::string& text2, const std::string& text3)
|
||||
{
|
||||
verify(type != Challenge && type != Leaderboard);
|
||||
std::lock_guard<std::mutex> _(mutex);
|
||||
u64 now = getTimeMs();
|
||||
if (type == Progress)
|
||||
|
@ -98,6 +100,36 @@ void Notification::hideChallenge(const std::string& image)
|
|||
endTime = getTimeMs();
|
||||
}
|
||||
|
||||
void Notification::showLeaderboard(u32 id, const std::string& text)
|
||||
{
|
||||
std::lock_guard<std::mutex> _(mutex);
|
||||
auto it = leaderboards.find(id);
|
||||
if (it == leaderboards.end())
|
||||
{
|
||||
if (leaderboards.empty())
|
||||
{
|
||||
this->type = Leaderboard;
|
||||
startTime = getTimeMs();
|
||||
endTime = NEVER_ENDS;
|
||||
}
|
||||
leaderboards[id] = text;
|
||||
}
|
||||
else {
|
||||
it->second = text;
|
||||
}
|
||||
}
|
||||
|
||||
void Notification::hideLeaderboard(u32 id)
|
||||
{
|
||||
std::lock_guard<std::mutex> _(mutex);
|
||||
auto it = leaderboards.find(id);
|
||||
if (it == leaderboards.end())
|
||||
return;
|
||||
leaderboards.erase(it);
|
||||
if (this->type == Leaderboard && leaderboards.empty())
|
||||
endTime = getTimeMs();
|
||||
}
|
||||
|
||||
bool Notification::draw()
|
||||
{
|
||||
std::lock_guard<std::mutex> _(mutex);
|
||||
|
@ -106,7 +138,14 @@ bool Notification::draw()
|
|||
u64 now = getTimeMs();
|
||||
if (now > endTime + END_ANIM_TIME)
|
||||
{
|
||||
if (!challenges.empty())
|
||||
if (!leaderboards.empty())
|
||||
{
|
||||
// Show current leaderboards
|
||||
type = Leaderboard;
|
||||
startTime = getTimeMs();
|
||||
endTime = NEVER_ENDS;
|
||||
}
|
||||
else if (!challenges.empty())
|
||||
{
|
||||
// Show current challenge indicators
|
||||
type = Challenge;
|
||||
|
@ -120,78 +159,114 @@ bool Notification::draw()
|
|||
return false;
|
||||
}
|
||||
}
|
||||
float alpha = 1.f;
|
||||
if (now > endTime)
|
||||
{
|
||||
// Fade out
|
||||
float alpha = (std::cos((now - endTime) / (float)END_ANIM_TIME * (float)M_PI) + 1.f) / 2.f;
|
||||
ImGui::GetStyle().Alpha = alpha;
|
||||
ImGui::SetNextWindowBgAlpha(alpha / 2.f);
|
||||
}
|
||||
else {
|
||||
ImGui::SetNextWindowBgAlpha(0.5f);
|
||||
}
|
||||
float y = ImGui::GetIO().DisplaySize.y;
|
||||
alpha = (std::cos((now - endTime) / (float)END_ANIM_TIME * (float)M_PI) + 1.f) / 2.f;
|
||||
float animY = 0.f;
|
||||
if (now - startTime < START_ANIM_TIME)
|
||||
// Slide up
|
||||
y += uiScaled(80.f) * (std::cos((now - startTime) / (float)START_ANIM_TIME * (float)M_PI) + 1.f) / 2.f;
|
||||
animY = (std::cos((now - startTime) / (float)START_ANIM_TIME * (float)M_PI) + 1.f) / 2.f;
|
||||
|
||||
ImGui::SetNextWindowPos(ImVec2(0, y), ImGuiCond_Always, ImVec2(0.f, 1.f)); // Lower left corner
|
||||
const ImVec2 padding = ImGui::GetStyle().WindowPadding;
|
||||
ImDrawList *dl = ImGui::GetForegroundDrawList();
|
||||
const ImU32 bg_col = alphaOverride(ImGui::GetColorU32(ImGuiCol_WindowBg), alpha / 2.f);
|
||||
const ImU32 borderCol = alphaOverride(ImGui::GetColorU32(ImGuiCol_Border), alpha);
|
||||
if (type == Challenge)
|
||||
{
|
||||
ImGui::Begin("##achievement", nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoNav
|
||||
| ImGuiWindowFlags_NoInputs);
|
||||
for (const auto& img : challenges)
|
||||
{
|
||||
img.draw(ScaledVec2(60.f, 60.f));
|
||||
ImGui::SameLine();
|
||||
const ScaledVec2 size(60.f, 60.f);
|
||||
const ImVec2 spacing(ImGui::GetStyle().ItemSpacing.x, 0.f);
|
||||
const ImVec2 totalSize = size * challenges.size() + spacing * (challenges.size() - 1) + padding * 2.f;
|
||||
ImVec2 pos(insetLeft, ImGui::GetIO().DisplaySize.y - totalSize.y * (1.f - animY));
|
||||
dl->AddRectFilled(pos, pos + totalSize, bg_col, 0.f);
|
||||
dl->AddRect(pos, pos + totalSize, borderCol, 0.f);
|
||||
|
||||
pos += padding;
|
||||
for (const auto& img : challenges) {
|
||||
img.draw(dl, pos, size, alpha);
|
||||
pos += spacing;
|
||||
}
|
||||
}
|
||||
else if (type == Leaderboard)
|
||||
{
|
||||
ImFont *font = ImGui::GetFont();
|
||||
const ImVec2 padding = ImGui::GetStyle().FramePadding;
|
||||
// iterate from the end
|
||||
ImVec2 pos(insetLeft + padding.x, ImGui::GetIO().DisplaySize.y - padding.y);
|
||||
for (auto it = leaderboards.rbegin(); it != leaderboards.rend(); ++it)
|
||||
{
|
||||
const std::string& text = it->second;
|
||||
ImVec2 size = font->CalcTextSizeA(font->FontSize, FLT_MAX, -1.f, text.c_str());
|
||||
ImVec2 psize = size + padding * 2;
|
||||
pos.y -= psize.y;
|
||||
dl->AddRectFilled(pos, pos + psize, bg_col, 0.f);
|
||||
ImVec2 tpos = pos + padding;
|
||||
const ImU32 col = alphaOverride(0xffffff, alpha);
|
||||
dl->AddText(font, font->FontSize, tpos, col, &text.front(), &text.back() + 1, FLT_MAX);
|
||||
pos.y -= padding.y;
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::SetNextWindowSizeConstraints(ScaledVec2(80.f, 80.f) + ImVec2(ImGui::GetStyle().WindowPadding.x * 2, 0.f), ImVec2(FLT_MAX, FLT_MAX));
|
||||
const float winPaddingX = ImGui::GetStyle().WindowPadding.x;
|
||||
ImguiStyleVar _(ImGuiStyleVar_WindowPadding, ImVec2{});
|
||||
|
||||
ImGui::Begin("##achievement", nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoNav
|
||||
| ImGuiWindowFlags_NoInputs);
|
||||
ImTextureID imageId = image.getId();
|
||||
const bool hasPic = imageId != ImTextureID{};
|
||||
if (ImGui::BeginTable("achievementNotif", hasPic ? 2 : 1, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoSavedSettings))
|
||||
const float hspacing = ImGui::GetStyle().ItemSpacing.x;
|
||||
const float vspacing = ImGui::GetStyle().ItemSpacing.y;
|
||||
const ScaledVec2 imgSize = image.getId() != ImTextureID{} ? ScaledVec2(80.f, 80.f) : ScaledVec2();
|
||||
// text size
|
||||
const float maxW = std::min(ImGui::GetIO().DisplaySize.x, uiScaled(640.f)) - padding.x
|
||||
- (imgSize.x != 0.f ? imgSize.x + hspacing : padding.x);
|
||||
ImFont *regularFont = ImGui::GetFont();
|
||||
ImVec2 textSize[3] {};
|
||||
ImVec2 totalSize(0.f, padding.y * 2);
|
||||
for (size_t i = 0; i < std::size(text); i++)
|
||||
{
|
||||
if (hasPic)
|
||||
ImGui::TableSetupColumn("icon", ImGuiTableColumnFlags_WidthFixed);
|
||||
ImGui::TableSetupColumn("text", ImGuiTableColumnFlags_WidthStretch);
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
if (hasPic)
|
||||
{
|
||||
image.draw(ScaledVec2(80.f, 80.f));
|
||||
ImGui::TableSetColumnIndex(1);
|
||||
}
|
||||
|
||||
float w = largeFont->CalcTextSizeA(largeFont->FontSize, FLT_MAX, -1.f, text[0].c_str()).x;
|
||||
w = std::max(w, ImGui::CalcTextSize(text[1].c_str()).x);
|
||||
w = std::max(w, ImGui::CalcTextSize(text[2].c_str()).x) + winPaddingX * 2;
|
||||
int lines = (int)!text[0].empty() + (int)!text[1].empty() + (int)!text[2].empty();
|
||||
ImguiStyleVar _(ImGuiStyleVar_WindowPadding, ImVec2{ hasPic ? 0.f : winPaddingX, (3 - lines) * ImGui::GetTextLineHeight() / 2 });
|
||||
if (ImGui::BeginChild("##text", ImVec2(w, 0), ImGuiChildFlags_AlwaysUseWindowPadding, ImGuiWindowFlags_None))
|
||||
{
|
||||
ImGui::PushFont(largeFont);
|
||||
ImGui::Text("%s", text[0].c_str());
|
||||
ImGui::PopFont();
|
||||
if (!text[1].empty())
|
||||
ImGui::TextColored(ImVec4(1, 1, 0, 0.7f), "%s", text[1].c_str());
|
||||
if (!text[2].empty())
|
||||
ImGui::TextColored(ImVec4(1, 1, 0, 0.7f), "%s", text[2].c_str());
|
||||
}
|
||||
ImGui::EndChild();
|
||||
ImGui::EndTable();
|
||||
if (text[i].empty())
|
||||
continue;
|
||||
const ImFont *font = i == 0 ? largeFont : regularFont;
|
||||
textSize[i] = font->CalcTextSizeA(font->FontSize, FLT_MAX, maxW, text[i].c_str());
|
||||
totalSize.x = std::max(totalSize.x, textSize[i].x);
|
||||
totalSize.y += textSize[i].y;
|
||||
}
|
||||
float topMargin = 0.f;
|
||||
// image / left padding
|
||||
if (imgSize.x != 0.f)
|
||||
{
|
||||
if (totalSize.y < imgSize.y)
|
||||
topMargin = (imgSize.y - totalSize.y) / 2.f;
|
||||
totalSize.x += imgSize.x + hspacing;
|
||||
totalSize.y = std::max(totalSize.y, imgSize.y);
|
||||
}
|
||||
else {
|
||||
totalSize.x += padding.x;
|
||||
}
|
||||
// right padding
|
||||
totalSize.x += padding.x;
|
||||
// border
|
||||
totalSize += ImVec2(2.f, 2.f);
|
||||
// draw background, border
|
||||
ImVec2 pos(insetLeft, ImGui::GetIO().DisplaySize.y - totalSize.y * (1.f - animY));
|
||||
dl->AddRectFilled(pos, pos + totalSize, bg_col, 0.f);
|
||||
dl->AddRect(pos, pos + totalSize, borderCol, 0.f);
|
||||
|
||||
// draw image and text
|
||||
pos += ImVec2(1.f, 1.f); // border
|
||||
if (imgSize.x != 0.f) {
|
||||
image.draw(dl, pos, imgSize, alpha);
|
||||
pos.x += imgSize.x + hspacing;
|
||||
}
|
||||
else {
|
||||
pos.x += padding.x;
|
||||
}
|
||||
pos.y += topMargin;
|
||||
for (size_t i = 0; i < std::size(text); i++)
|
||||
{
|
||||
if (text[i].empty())
|
||||
continue;
|
||||
const ImFont *font = i == 0 ? largeFont : regularFont;
|
||||
const ImU32 col = alphaOverride(i == 0 ? 0xffffff : 0x00ffff, alpha);
|
||||
dl->AddText(font, font->FontSize, pos, col, &text[i].front(), &text[i].back() + 1, maxW);
|
||||
pos.y += textSize[i].y + vspacing;
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
ImGui::GetStyle().Alpha = 1.f;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "gui_util.h"
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
namespace achievements
|
||||
{
|
||||
|
@ -35,13 +36,16 @@ public:
|
|||
Unlocked,
|
||||
Progress,
|
||||
Mastery,
|
||||
Challenge,
|
||||
Challenge, // internal use
|
||||
Leaderboard, // internal use
|
||||
Error
|
||||
};
|
||||
void notify(Type type, const std::string& image, const std::string& text1,
|
||||
const std::string& text2 = {}, const std::string& text3 = {});
|
||||
void showChallenge(const std::string& image);
|
||||
void hideChallenge(const std::string& image);
|
||||
void showLeaderboard(u32 id, const std::string& text);
|
||||
void hideLeaderboard(u32 id);
|
||||
bool draw();
|
||||
|
||||
private:
|
||||
|
@ -52,6 +56,7 @@ private:
|
|||
std::string text[3];
|
||||
std::mutex mutex;
|
||||
std::vector<ImguiTexture> challenges;
|
||||
std::map<u32, std::string> leaderboards;
|
||||
};
|
||||
|
||||
extern Notification notifier;
|
||||
|
|
|
@ -36,6 +36,7 @@ static std::vector<hostfs::FileInfo> folderFiles;
|
|||
bool subfolders_read;
|
||||
|
||||
extern int insetLeft, insetRight, insetTop, insetBottom;
|
||||
extern ImFont *largeFont;
|
||||
void error_popup();
|
||||
|
||||
namespace hostfs
|
||||
|
@ -728,6 +729,19 @@ void ImguiTexture::draw(const ImVec2& size, const ImVec4& tint_col, const ImVec4
|
|||
}
|
||||
}
|
||||
|
||||
void ImguiTexture::draw(ImDrawList *drawList, const ImVec2& pos, const ImVec2& size, float alpha) const
|
||||
{
|
||||
ImTextureID id = getId();
|
||||
if (id == ImTextureID{})
|
||||
return;
|
||||
float ar = imguiDriver->getAspectRatio(id);
|
||||
ImVec2 uv0, uv1;
|
||||
setUV(ar, uv0, uv1);
|
||||
ImVec2 pos_b = pos + size;
|
||||
u32 col = alphaOverride(0xffffff, alpha);
|
||||
drawList->AddImage(id, pos, pos_b, uv0, uv1, col);
|
||||
}
|
||||
|
||||
bool ImguiTexture::button(const char* str_id, const ImVec2& image_size, const std::string& title,
|
||||
const ImVec4& bg_col, const ImVec4& tint_col) const
|
||||
{
|
||||
|
@ -813,19 +827,19 @@ bool Toast::draw()
|
|||
// Fade out
|
||||
alpha = (std::cos((now - endTime) / (float)END_ANIM_TIME * (float)M_PI) + 1.f) / 2.f;
|
||||
|
||||
extern ImFont *largeFont; // FIXME
|
||||
ImFont *regularFont = ImGui::GetFont();
|
||||
const float maxW = uiScaled(640.f);
|
||||
const ImVec2 titleSize = title.empty() ? ImVec2()
|
||||
: largeFont->CalcTextSizeA(largeFont->FontSize, FLT_MAX, maxW, &title.front(), &title.back() + 1);
|
||||
const ImVec2 msgSize = message.empty() ? ImVec2()
|
||||
: regularFont->CalcTextSizeA(regularFont->FontSize, FLT_MAX, maxW, &message.front(), &message.back() + 1);
|
||||
const ScaledVec2 padding(10.f, 10.f);
|
||||
const ScaledVec2 spacing(0.f, 5.f);
|
||||
const ImVec2 totalSize = titleSize + spacing + msgSize + padding * 2.f;
|
||||
const ScaledVec2 padding(5.f, 4.f);
|
||||
const ScaledVec2 spacing(0.f, 2.f);
|
||||
ImVec2 totalSize(std::max(titleSize.x, msgSize.x), titleSize.y + msgSize.y);
|
||||
totalSize += padding * 2.f + spacing * (float)(!title.empty() && !message.empty());
|
||||
|
||||
const ImVec2 displaySize(ImGui::GetIO().DisplaySize);
|
||||
ImVec2 pos(0.f, displaySize.y - totalSize.y);
|
||||
ImVec2 pos(insetLeft, displaySize.y - totalSize.y);
|
||||
if (now - startTime < START_ANIM_TIME)
|
||||
// Slide up
|
||||
pos.y += totalSize.y * (std::cos((now - startTime) / (float)START_ANIM_TIME * (float)M_PI) + 1.f) / 2.f;
|
||||
|
@ -840,7 +854,7 @@ bool Toast::draw()
|
|||
{
|
||||
const ImU32 col = alphaOverride(ImGui::GetColorU32(ImGuiCol_Text), alpha);
|
||||
dl->AddText(largeFont, largeFont->FontSize, pos, col, &title.front(), &title.back() + 1, maxW);
|
||||
pos += spacing + ImVec2(0.f, titleSize.y);
|
||||
pos.y += spacing.y + titleSize.y;
|
||||
}
|
||||
if (!message.empty())
|
||||
{
|
||||
|
|
|
@ -204,6 +204,7 @@ public:
|
|||
|
||||
void draw(const ImVec2& size, const ImVec4& tint_col = ImVec4(1, 1, 1, 1),
|
||||
const ImVec4& border_col = ImVec4(0, 0, 0, 0)) const;
|
||||
void draw(ImDrawList *drawList, const ImVec2& pos, const ImVec2& size, float alpha = 1.f) const;
|
||||
bool button(const char* str_id, const ImVec2& image_size, const std::string& title = {}, const ImVec4& bg_col = ImVec4(0, 0, 0, 0),
|
||||
const ImVec4& tint_col = ImVec4(1, 1, 1, 1)) const;
|
||||
|
||||
|
|
|
@ -196,7 +196,7 @@ static retro_rumble_interface rumble;
|
|||
static void refresh_devices(bool first_startup);
|
||||
static void init_disk_control_interface();
|
||||
static bool read_m3u(const char *file);
|
||||
void gui_display_notification(const char *msg, int duration);
|
||||
void gui_display_notification(const char *msg, int duration, const char *details = nullptr);
|
||||
static void updateVibration(u32 port, float power, float inclination, u32 durationMs);
|
||||
|
||||
static std::string game_data;
|
||||
|
@ -3702,7 +3702,7 @@ static bool read_m3u(const char *file)
|
|||
return disk_index != 0;
|
||||
}
|
||||
|
||||
void gui_display_notification(const char *msg, int duration)
|
||||
void gui_display_notification(const char *msg, int duration, const char *details)
|
||||
{
|
||||
retro_message retromsg;
|
||||
retromsg.msg = msg;
|
||||
|
|
Loading…
Reference in New Issue