Add support for notification that can survive application changes

This commit is contained in:
Maschell 2024-04-26 13:53:15 +02:00
parent 42727408df
commit a2cf5293d8
5 changed files with 79 additions and 27 deletions

View File

@ -1,6 +1,6 @@
FROM ghcr.io/wiiu-env/devkitppc:20240423
COPY --from=ghcr.io/wiiu-env/libnotifications:20230621 /artifacts $DEVKITPRO
COPY --from=ghcr.io/wiiu-env/libnotifications:20240426 /artifacts $DEVKITPRO
COPY --from=ghcr.io/wiiu-env/libmappedmemory:20230621 /artifacts $DEVKITPRO
COPY --from=ghcr.io/wiiu-env/libfunctionpatcher:20230621 /artifacts $DEVKITPRO
COPY --from=ghcr.io/wiiu-env/wiiumodulesystem:20240424 /artifacts $DEVKITPRO

View File

@ -9,17 +9,28 @@ void ExportCleanUp() {
std::lock_guard<std::mutex> lock(gNotificationListMutex);
gNotificationList.clear();
std::lock_guard overlay_lock(gOverlayFrameMutex);
// Remove notification in queue that should not survive
std::vector<std::shared_ptr<Notification>> keepQueue;
for (const auto &notification : gOverlayQueueDuringStartup) {
if (notification->isKeepUntilShown()) {
keepQueue.push_back(notification);
} else {
}
}
gOverlayQueueDuringStartup.clear();
gOverlayQueueDuringStartup = keepQueue;
}
NotificationModuleStatus NMAddStaticNotification(const char *text,
NotificationModuleNotificationType type,
float durationBeforeFadeOutInSeconds,
float shakeDurationInSeconds,
NMColor textColor,
NMColor backgroundColor,
void (*finishFunc)(NotificationModuleHandle, void *context),
void *context) {
NotificationModuleStatus NMAddStaticNotificationV2(const char *text,
NotificationModuleNotificationType type,
float durationBeforeFadeOutInSeconds,
float shakeDurationInSeconds,
NMColor textColor,
NMColor backgroundColor,
void (*finishFunc)(NotificationModuleHandle, void *context),
void *context,
bool keepUntilShown) {
NotificationStatus status;
switch (type) {
@ -40,14 +51,16 @@ NotificationModuleStatus NMAddStaticNotification(const char *text,
(GX2Color){textColor.r, textColor.g, textColor.b, textColor.a},
(GX2Color){backgroundColor.r, backgroundColor.g, backgroundColor.b, backgroundColor.a},
finishFunc,
context);
context,
nullptr,
keepUntilShown);
if (!notification) {
return NOTIFICATION_MODULE_RESULT_ALLOCATION_FAILED;
}
{
std::lock_guard lock(gOverlayFrameMutex);
if (gOverlayFrame) {
if (gOverlayFrame && gDrawReady) {
gOverlayFrame->addNotification(std::move(notification));
} else {
gOverlayQueueDuringStartup.push_back(std::move(notification));
@ -57,6 +70,18 @@ NotificationModuleStatus NMAddStaticNotification(const char *text,
return NOTIFICATION_MODULE_RESULT_SUCCESS;
}
NotificationModuleStatus NMAddStaticNotification(const char *text,
NotificationModuleNotificationType type,
float durationBeforeFadeOutInSeconds,
float shakeDurationInSeconds,
NMColor textColor,
NMColor backgroundColor,
void (*finishFunc)(NotificationModuleHandle, void *context),
void *context) {
return NMAddStaticNotificationV2(text, type, durationBeforeFadeOutInSeconds, shakeDurationInSeconds, textColor, backgroundColor, finishFunc, context, false);
}
void NMNotificationRemovedFromOverlay(Notification *notification) {
if (notification) {
auto handle = notification->getHandle();
@ -66,12 +91,13 @@ void NMNotificationRemovedFromOverlay(Notification *notification) {
}
}
NotificationModuleStatus NMAddDynamicNotification(const char *text,
NMColor textColor,
NMColor backgroundColor,
void (*finishFunc)(NotificationModuleHandle, void *context),
void *context,
NotificationModuleHandle *outHandle) {
NotificationModuleStatus NMAddDynamicNotificationV2(const char *text,
NMColor textColor,
NMColor backgroundColor,
void (*finishFunc)(NotificationModuleHandle, void *context),
void *context,
bool keep_until_shown,
NotificationModuleHandle *outHandle) {
if (outHandle == nullptr) {
return NOTIFICATION_MODULE_RESULT_INVALID_ARGUMENT;
}
@ -86,7 +112,8 @@ NotificationModuleStatus NMAddDynamicNotification(const char *text,
(GX2Color){backgroundColor.r, backgroundColor.g, backgroundColor.b, backgroundColor.a},
finishFunc,
context,
NMNotificationRemovedFromOverlay);
NMNotificationRemovedFromOverlay,
keep_until_shown);
if (!notification) {
return NOTIFICATION_MODULE_RESULT_ALLOCATION_FAILED;
}
@ -108,6 +135,15 @@ NotificationModuleStatus NMAddDynamicNotification(const char *text,
return NOTIFICATION_MODULE_RESULT_SUCCESS;
}
NotificationModuleStatus NMAddDynamicNotification(const char *text,
NMColor textColor,
NMColor backgroundColor,
void (*finishFunc)(NotificationModuleHandle, void *context),
void *context,
NotificationModuleHandle *outHandle) {
return NMAddDynamicNotificationV2(text, textColor, backgroundColor, finishFunc, context, false, outHandle);
}
NotificationModuleStatus NMUpdateDynamicNotificationText(NotificationModuleHandle handle,
const char *text) {
NotificationModuleStatus res = NOTIFICATION_MODULE_RESULT_INVALID_HANDLE;
@ -196,10 +232,12 @@ NotificationModuleStatus NMGetVersion(NotificationModuleAPIVersion *outVersion)
if (outVersion == nullptr) {
return NOTIFICATION_MODULE_RESULT_INVALID_ARGUMENT;
}
*outVersion = 1;
*outVersion = 2;
return NOTIFICATION_MODULE_RESULT_SUCCESS;
}
WUMS_EXPORT_FUNCTION(NMAddDynamicNotificationV2);
WUMS_EXPORT_FUNCTION(NMAddStaticNotificationV2);
WUMS_EXPORT_FUNCTION(NMAddDynamicNotification);
WUMS_EXPORT_FUNCTION(NMAddStaticNotification);
WUMS_EXPORT_FUNCTION(NMUpdateDynamicNotificationText);

View File

@ -71,8 +71,18 @@ void drawScreenshotSavedTexture2(GX2ColorBuffer *colorBuffer, GX2ScanTarget scan
drawIntoColorBuffer(colorBuffer, gOverlayFrame, scan_target);
}
static void TryAddFromQueue() {
std::lock_guard overlay_lock(gOverlayFrameMutex);
// Add notification that had been called before the overlay was ready
for (const auto &notification : gOverlayQueueDuringStartup) {
gOverlayFrame->addNotification(notification);
}
gOverlayQueueDuringStartup.clear();
}
DECL_FUNCTION(void, GX2CopyColorBufferToScanBuffer, const GX2ColorBuffer *colorBuffer, GX2ScanTarget scan_target) {
gDrawReady = true;
TryAddFromQueue();
if (drawScreenshotSavedTexture(colorBuffer, scan_target)) {
// if it returns true we don't need to call GX2CopyColorBufferToScanBuffer
return;
@ -117,12 +127,6 @@ DECL_FUNCTION(void, GX2Init, uint32_t attributes) {
OSFatal("NotificationModule: Failed to alloc gOverlayFrame");
}
// Add notification that had been called before the overlay was ready
for (const auto &notification : gOverlayQueueDuringStartup) {
gOverlayFrame->addNotification(notification);
}
gOverlayQueueDuringStartup.clear();
// Allocate shader.
if (ColorShader::instance() == nullptr) {
OSFatal("NotificationModule: Failed to alloc ColorShader");
@ -143,6 +147,7 @@ DECL_FUNCTION(void, GX2Init, uint32_t attributes) {
DECL_FUNCTION(void, GX2MarkScanBufferCopied, GX2ScanTarget scan_target) {
gDrawReady = true;
TryAddFromQueue();
if (scan_target == GX2_SCAN_TARGET_TV) {
drawScreenshotSavedTexture2(&lastTVColorBuffer, scan_target);
} else {

View File

@ -8,7 +8,8 @@ Notification::Notification(const std::string &overlayText,
GX2Color backgroundColor,
void (*finishFunc)(NotificationModuleHandle, void *),
void *context,
void (*removedFromOverlayCallback)(Notification *)) : GuiFrame(0, 0), mBackground(0, 0, backgroundColor) {
void (*removedFromOverlayCallback)(Notification *),
bool keepUntilShown) : GuiFrame(0, 0), mBackground(0, 0, backgroundColor) {
mFinishFunction = finishFunc;
mFinishFunctionContext = context;
mRemovedFromOverlayCallback = removedFromOverlayCallback;
@ -20,6 +21,7 @@ Notification::Notification(const std::string &overlayText,
mNotificationText.setPosition(0, 0);
mNotificationText.setFontSize(20);
mNotificationText.setAlignment(ALIGN_CENTERED);
mKeepUntilShown = keepUntilShown;
updateStatus(status);

View File

@ -35,7 +35,8 @@ public:
GX2Color backgroundColor = {100, 100, 100, 255},
void (*finishFunc)(NotificationModuleHandle, void *) = nullptr,
void *context = nullptr,
void (*removedFromOverlayCallback)(Notification *) = nullptr);
void (*removedFromOverlayCallback)(Notification *) = nullptr,
bool keepUntilShown = false);
~Notification() override;
@ -90,6 +91,10 @@ public:
mPositionSet = true;
}
[[nodiscard]] bool isKeepUntilShown() const {
return mKeepUntilShown;
}
private:
std::function<void(NotificationModuleHandle, void *)> mFinishFunction;
std::function<void(Notification *)> mRemovedFromOverlayCallback;
@ -106,6 +111,8 @@ private:
bool mTextDirty = false;
bool mPositionSet = false;
bool mKeepUntilShown = false;
NotificationStatus mStatus = NOTIFICATION_STATUS_INFO;
NotificationInternalStatus mInternalStatus = NOTIFICATION_STATUS_NOTHING;
};