mirror of
https://github.com/wiiu-env/NotificationModule.git
synced 2024-11-17 01:09:16 +01:00
Add support for notification that can survive application changes
This commit is contained in:
parent
42727408df
commit
a2cf5293d8
@ -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
|
||||||
|
@ -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 ¬ification : 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);
|
||||||
|
@ -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 ¬ification : 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 ¬ification : 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 {
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user