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 4843245e44
5 changed files with 79 additions and 27 deletions

View File

@ -1,6 +1,6 @@
FROM ghcr.io/wiiu-env/devkitppc:20240423 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/libmappedmemory:20230621 /artifacts $DEVKITPRO
COPY --from=ghcr.io/wiiu-env/libfunctionpatcher:20230621 /artifacts $DEVKITPRO COPY --from=ghcr.io/wiiu-env/libfunctionpatcher:20230621 /artifacts $DEVKITPRO
COPY --from=ghcr.io/wiiu-env/wiiumodulesystem:20240424 /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); std::lock_guard<std::mutex> lock(gNotificationListMutex);
gNotificationList.clear(); gNotificationList.clear();
std::lock_guard overlay_lock(gOverlayFrameMutex); 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.clear();
gOverlayQueueDuringStartup = keepQueue;
} }
NotificationModuleStatus NMAddStaticNotification(const char *text, NotificationModuleStatus NMAddStaticNotificationV2(const char *text,
NotificationModuleNotificationType type, NotificationModuleNotificationType type,
float durationBeforeFadeOutInSeconds, float durationBeforeFadeOutInSeconds,
float shakeDurationInSeconds, float shakeDurationInSeconds,
NMColor textColor, NMColor textColor,
NMColor backgroundColor, NMColor backgroundColor,
void (*finishFunc)(NotificationModuleHandle, void *context), void (*finishFunc)(NotificationModuleHandle, void *context),
void *context) { void *context,
bool keepUntilShown) {
NotificationStatus status; NotificationStatus status;
switch (type) { switch (type) {
@ -40,14 +51,16 @@ NotificationModuleStatus NMAddStaticNotification(const char *text,
(GX2Color){textColor.r, textColor.g, textColor.b, textColor.a}, (GX2Color){textColor.r, textColor.g, textColor.b, textColor.a},
(GX2Color){backgroundColor.r, backgroundColor.g, backgroundColor.b, backgroundColor.a}, (GX2Color){backgroundColor.r, backgroundColor.g, backgroundColor.b, backgroundColor.a},
finishFunc, finishFunc,
context); context,
nullptr,
keepUntilShown);
if (!notification) { if (!notification) {
return NOTIFICATION_MODULE_RESULT_ALLOCATION_FAILED; return NOTIFICATION_MODULE_RESULT_ALLOCATION_FAILED;
} }
{ {
std::lock_guard lock(gOverlayFrameMutex); std::lock_guard lock(gOverlayFrameMutex);
if (gOverlayFrame) { if (gOverlayFrame && gDrawReady) {
gOverlayFrame->addNotification(std::move(notification)); gOverlayFrame->addNotification(std::move(notification));
} else { } else {
gOverlayQueueDuringStartup.push_back(std::move(notification)); gOverlayQueueDuringStartup.push_back(std::move(notification));
@ -57,6 +70,18 @@ NotificationModuleStatus NMAddStaticNotification(const char *text,
return NOTIFICATION_MODULE_RESULT_SUCCESS; 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) { void NMNotificationRemovedFromOverlay(Notification *notification) {
if (notification) { if (notification) {
auto handle = notification->getHandle(); auto handle = notification->getHandle();
@ -66,11 +91,12 @@ void NMNotificationRemovedFromOverlay(Notification *notification) {
} }
} }
NotificationModuleStatus NMAddDynamicNotification(const char *text, NotificationModuleStatus NMAddDynamicNotificationV2(const char *text,
NMColor textColor, NMColor textColor,
NMColor backgroundColor, NMColor backgroundColor,
void (*finishFunc)(NotificationModuleHandle, void *context), void (*finishFunc)(NotificationModuleHandle, void *context),
void *context, void *context,
bool keep_until_shown,
NotificationModuleHandle *outHandle) { NotificationModuleHandle *outHandle) {
if (outHandle == nullptr) { if (outHandle == nullptr) {
return NOTIFICATION_MODULE_RESULT_INVALID_ARGUMENT; return NOTIFICATION_MODULE_RESULT_INVALID_ARGUMENT;
@ -86,7 +112,8 @@ NotificationModuleStatus NMAddDynamicNotification(const char *text,
(GX2Color){backgroundColor.r, backgroundColor.g, backgroundColor.b, backgroundColor.a}, (GX2Color){backgroundColor.r, backgroundColor.g, backgroundColor.b, backgroundColor.a},
finishFunc, finishFunc,
context, context,
NMNotificationRemovedFromOverlay); NMNotificationRemovedFromOverlay,
keep_until_shown);
if (!notification) { if (!notification) {
return NOTIFICATION_MODULE_RESULT_ALLOCATION_FAILED; return NOTIFICATION_MODULE_RESULT_ALLOCATION_FAILED;
} }
@ -108,6 +135,15 @@ NotificationModuleStatus NMAddDynamicNotification(const char *text,
return NOTIFICATION_MODULE_RESULT_SUCCESS; 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, NotificationModuleStatus NMUpdateDynamicNotificationText(NotificationModuleHandle handle,
const char *text) { const char *text) {
NotificationModuleStatus res = NOTIFICATION_MODULE_RESULT_INVALID_HANDLE; NotificationModuleStatus res = NOTIFICATION_MODULE_RESULT_INVALID_HANDLE;
@ -196,10 +232,12 @@ NotificationModuleStatus NMGetVersion(NotificationModuleAPIVersion *outVersion)
if (outVersion == nullptr) { if (outVersion == nullptr) {
return NOTIFICATION_MODULE_RESULT_INVALID_ARGUMENT; return NOTIFICATION_MODULE_RESULT_INVALID_ARGUMENT;
} }
*outVersion = 1; *outVersion = 2;
return NOTIFICATION_MODULE_RESULT_SUCCESS; return NOTIFICATION_MODULE_RESULT_SUCCESS;
} }
WUMS_EXPORT_FUNCTION(NMAddDynamicNotificationV2);
WUMS_EXPORT_FUNCTION(NMAddStaticNotificationV2);
WUMS_EXPORT_FUNCTION(NMAddDynamicNotification); WUMS_EXPORT_FUNCTION(NMAddDynamicNotification);
WUMS_EXPORT_FUNCTION(NMAddStaticNotification); WUMS_EXPORT_FUNCTION(NMAddStaticNotification);
WUMS_EXPORT_FUNCTION(NMUpdateDynamicNotificationText); WUMS_EXPORT_FUNCTION(NMUpdateDynamicNotificationText);

View File

@ -71,8 +71,18 @@ void drawScreenshotSavedTexture2(GX2ColorBuffer *colorBuffer, GX2ScanTarget scan
drawIntoColorBuffer(colorBuffer, gOverlayFrame, scan_target); 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) { DECL_FUNCTION(void, GX2CopyColorBufferToScanBuffer, const GX2ColorBuffer *colorBuffer, GX2ScanTarget scan_target) {
gDrawReady = true; gDrawReady = true;
TryAddFromQueue();
if (drawScreenshotSavedTexture(colorBuffer, scan_target)) { if (drawScreenshotSavedTexture(colorBuffer, scan_target)) {
// if it returns true we don't need to call GX2CopyColorBufferToScanBuffer // if it returns true we don't need to call GX2CopyColorBufferToScanBuffer
return; return;
@ -117,12 +127,6 @@ DECL_FUNCTION(void, GX2Init, uint32_t attributes) {
OSFatal("NotificationModule: Failed to alloc gOverlayFrame"); 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. // Allocate shader.
if (ColorShader::instance() == nullptr) { if (ColorShader::instance() == nullptr) {
OSFatal("NotificationModule: Failed to alloc ColorShader"); OSFatal("NotificationModule: Failed to alloc ColorShader");
@ -143,6 +147,7 @@ DECL_FUNCTION(void, GX2Init, uint32_t attributes) {
DECL_FUNCTION(void, GX2MarkScanBufferCopied, GX2ScanTarget scan_target) { DECL_FUNCTION(void, GX2MarkScanBufferCopied, GX2ScanTarget scan_target) {
gDrawReady = true; gDrawReady = true;
TryAddFromQueue();
if (scan_target == GX2_SCAN_TARGET_TV) { if (scan_target == GX2_SCAN_TARGET_TV) {
drawScreenshotSavedTexture2(&lastTVColorBuffer, scan_target); drawScreenshotSavedTexture2(&lastTVColorBuffer, scan_target);
} else { } else {

View File

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

View File

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