Add option to change the button combo

This commit is contained in:
Maschell 2022-09-24 17:57:29 +02:00
parent 51b0a754b7
commit f4c2196ce1
4 changed files with 344 additions and 8 deletions

View File

@ -11,12 +11,14 @@ The screenshots will be saved on the SD card in the folder `sd:/wiiu/screenshots
3. Requires the [MemoryMappingModule](https://github.com/wiiu-env/MemoryMappingModule) in `sd:/wiiu/environments/[ENVIRONMENT]/modules`.
## Usage
Press ZL + L + ZR + R on the GamePad to take a screenshot.
Press a button combo (default is L + R + ZL + ZR) on the GamePad to take a screenshot.
Via the plugin config menu (press L, DPAD Down and Minus on the GamePad, Pro Controller or Classic Controller) you can configure the plugin. The available options are the following:
- **Settings**:
- Enabled: (Default is true)
- Enables or disables the screenshot plugin.
- Button combo: (Default is L + R + ZL + ZR)
- Changes the button combo for taking screenshots.
- Screen: (Default is TV and GamePad)
- Determines from which screen a screenshot should be taken. Possible options: TV & GamePad, TV only, GamePad only.
- Output format: (Default is JPEG)

View File

@ -1,5 +1,6 @@
#include "main.h"
#include "retain_vars.hpp"
#include "utils/WUPSConfigItemButtonCombo.h"
#include "utils/logger.h"
#include <coreinit/cache.h>
#include <coreinit/title.h>
@ -25,6 +26,7 @@ WUPS_USE_WUT_DEVOPTAB();
WUPS_USE_STORAGE("screenshot_plugin");
#define ENABLED_CONFIG_STRING "enabled"
#define BUTTON_COMBO_CONFIG_STRING "buttonCombo"
#define FORMAT_CONFIG_STRING "format"
#define QUALITY_CONFIG_STRING "quality"
#define SCREEN_CONFIG_STRING "screen"
@ -41,7 +43,7 @@ INITIALIZE_PLUGIN() {
DEBUG_FUNCTION_LINE_ERR("Failed to open storage %s (%d)", WUPS_GetStorageStatusStr(storageRes), storageRes);
} else {
// Try to get value from storage
if ((storageRes = WUPS_GetInt(nullptr, ENABLED_CONFIG_STRING, reinterpret_cast<int32_t *>(&gEnabled))) == WUPS_STORAGE_ERROR_NOT_FOUND) {
if ((storageRes = WUPS_GetBool(nullptr, ENABLED_CONFIG_STRING, &gEnabled)) == WUPS_STORAGE_ERROR_NOT_FOUND) {
// Add the value to the storage if it's missing.
if (WUPS_StoreBool(nullptr, ENABLED_CONFIG_STRING, gEnabled) != WUPS_STORAGE_ERROR_SUCCESS) {
DEBUG_FUNCTION_LINE_ERR("Failed to store value");
@ -52,7 +54,7 @@ INITIALIZE_PLUGIN() {
// Try to get value from storage
if ((storageRes = WUPS_GetInt(nullptr, FORMAT_CONFIG_STRING, reinterpret_cast<int32_t *>(&gOutputFormat))) == WUPS_STORAGE_ERROR_NOT_FOUND) {
// Add the value to the storage if it's missing.
if (WUPS_StoreBool(nullptr, FORMAT_CONFIG_STRING, gOutputFormat) != WUPS_STORAGE_ERROR_SUCCESS) {
if (WUPS_StoreInt(nullptr, FORMAT_CONFIG_STRING, gOutputFormat) != WUPS_STORAGE_ERROR_SUCCESS) {
DEBUG_FUNCTION_LINE_ERR("Failed to store value");
}
} else if (storageRes != WUPS_STORAGE_ERROR_SUCCESS) {
@ -79,6 +81,16 @@ INITIALIZE_PLUGIN() {
DEBUG_FUNCTION_LINE_ERR("Failed to get value %s (%d)", WUPS_GetStorageStatusStr(storageRes), storageRes);
}
// Try to get value from storage
if ((storageRes = WUPS_GetInt(nullptr, BUTTON_COMBO_CONFIG_STRING, reinterpret_cast<int32_t *>(&gButtonCombo))) == WUPS_STORAGE_ERROR_NOT_FOUND) {
// Add the value to the storage if it's missing.
if (WUPS_StoreInt(nullptr, BUTTON_COMBO_CONFIG_STRING, (int32_t) gButtonCombo) != WUPS_STORAGE_ERROR_SUCCESS) {
DEBUG_FUNCTION_LINE_ERR("Failed to store value");
}
} else if (storageRes != WUPS_STORAGE_ERROR_SUCCESS) {
DEBUG_FUNCTION_LINE_ERR("Failed to get value %s (%d)", WUPS_GetStorageStatusStr(storageRes), storageRes);
}
// Close storage
if (WUPS_CloseStorage() != WUPS_STORAGE_ERROR_SUCCESS) {
DEBUG_FUNCTION_LINE_ERR("Failed to close storage");
@ -139,12 +151,21 @@ void boolItemCallback(ConfigItemBoolean *item, bool newValue) {
DEBUG_FUNCTION_LINE("New value in %s changed: %d", item->configId, newValue);
if (std::string_view(item->configId) == ENABLED_CONFIG_STRING) {
gEnabled = (ImageOutputFormatEnum) newValue;
WUPS_StoreBool(nullptr, item->configId, gEnabled);
}
}
}
void buttonComboItemChanged(ConfigItemButtonCombo *item, uint32_t newValue) {
if (item && item->configId) {
DEBUG_FUNCTION_LINE("New value in %s changed: %d", item->configId, newValue);
if (std::string_view(item->configId) == BUTTON_COMBO_CONFIG_STRING) {
gButtonCombo = newValue;
WUPS_StoreInt(nullptr, item->configId, (int32_t) gButtonCombo);
}
}
}
WUPS_GET_CONFIG() {
// We open the storage, so we can persist the configuration the user did.
if (WUPS_OpenStorage() != WUPS_STORAGE_ERROR_SUCCESS) {
@ -160,6 +181,8 @@ WUPS_GET_CONFIG() {
WUPSConfigItemBoolean_AddToCategoryHandled(config, setting, ENABLED_CONFIG_STRING, "Enabled", gEnabled, &boolItemCallback);
WUPSConfigItemButtonCombo_AddToCategoryHandled(config, setting, BUTTON_COMBO_CONFIG_STRING, "Button combo", gButtonCombo, &buttonComboItemChanged);
ConfigItemMultipleValuesPair source[3];
source[0].value = IMAGE_SOURCE_TV_AND_DRC;
source[0].valueName = (char *) "TV & GamePad";

View File

@ -0,0 +1,268 @@
#include "WUPSConfigItemButtonCombo.h"
#include <coreinit/debug.h>
#include <coreinit/thread.h>
#include <coreinit/time.h>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vpad/input.h>
#include <wups.h>
std::string getButtonChar(VPADButtons value) {
std::string combo;
if (value & VPAD_BUTTON_A) {
return "\ue000";
}
if (value & VPAD_BUTTON_B) {
return "\ue001";
}
if (value & VPAD_BUTTON_X) {
return "\ue002";
}
if (value & VPAD_BUTTON_Y) {
return "\ue003";
}
if (value & VPAD_BUTTON_L) {
return "\ue083";
}
if (value & VPAD_BUTTON_R) {
return "\ue084";
}
if (value & VPAD_BUTTON_ZL) {
return "\ue085";
}
if (value & VPAD_BUTTON_ZR) {
return "\ue086";
}
if (value & VPAD_BUTTON_UP) {
return "\ue079";
}
if (value & VPAD_BUTTON_DOWN) {
return "\ue07A";
}
if (value & VPAD_BUTTON_LEFT) {
return "\ue07B";
}
if (value & VPAD_BUTTON_RIGHT) {
return "\ue07C";
}
if (value & VPAD_BUTTON_STICK_L) {
return "\ue081";
}
if (value & VPAD_BUTTON_STICK_R) {
return "\ue082";
}
if (value & VPAD_BUTTON_PLUS) {
return "\ue045";
}
if (value & VPAD_BUTTON_MINUS) {
return "\ue046";
}
return "?";
}
std::string getComboAsString(uint32_t value) {
std::string combo;
if (value & VPAD_BUTTON_A) {
combo += getButtonChar(VPAD_BUTTON_A).append("+");
}
if (value & VPAD_BUTTON_B) {
combo += getButtonChar(VPAD_BUTTON_B).append("+");
}
if (value & VPAD_BUTTON_X) {
combo += getButtonChar(VPAD_BUTTON_X).append("+");
}
if (value & VPAD_BUTTON_Y) {
combo += getButtonChar(VPAD_BUTTON_Y).append("+");
}
if (value & VPAD_BUTTON_L) {
combo += getButtonChar(VPAD_BUTTON_L).append("+");
}
if (value & VPAD_BUTTON_R) {
combo += getButtonChar(VPAD_BUTTON_R).append("+");
}
if (value & VPAD_BUTTON_ZL) {
combo += getButtonChar(VPAD_BUTTON_ZL).append("+");
}
if (value & VPAD_BUTTON_ZR) {
combo += getButtonChar(VPAD_BUTTON_ZR).append("+");
}
if (value & VPAD_BUTTON_UP) {
combo += getButtonChar(VPAD_BUTTON_UP).append("+");
}
if (value & VPAD_BUTTON_DOWN) {
combo += getButtonChar(VPAD_BUTTON_DOWN).append("+");
}
if (value & VPAD_BUTTON_LEFT) {
combo += getButtonChar(VPAD_BUTTON_LEFT).append("+");
}
if (value & VPAD_BUTTON_RIGHT) {
combo += getButtonChar(VPAD_BUTTON_RIGHT).append("+");
}
if (value & VPAD_BUTTON_STICK_L) {
combo += getButtonChar(VPAD_BUTTON_STICK_L).append("+");
}
if (value & VPAD_BUTTON_STICK_R) {
combo += getButtonChar(VPAD_BUTTON_STICK_R).append("+");
}
if (value & VPAD_BUTTON_PLUS) {
combo += getButtonChar(VPAD_BUTTON_PLUS).append("+");
}
if (value & VPAD_BUTTON_MINUS) {
combo += getButtonChar(VPAD_BUTTON_MINUS).append("+");
}
if (combo.ends_with("+")) {
combo.pop_back();
}
return combo;
}
int32_t WUPSConfigItemButtonCombo_getCurrentValueDisplay(void *context, char *out_buf, int32_t out_size) {
auto *item = (ConfigItemButtonCombo *) context;
snprintf(out_buf, out_size, "%s", getComboAsString(item->value).c_str());
return 0;
}
bool WUPSConfigItemButtonCombo_callCallback(void *context) {
auto *item = (ConfigItemButtonCombo *) context;
if (item->callback != nullptr) {
((ButtonComboValueChangedCallback) (item->callback))(item, item->value);
return true;
}
return false;
}
void checkForHold(ConfigItemButtonCombo *item) {
uint32_t lastHold = 0;
uint32_t holdFor = 0;
uint32_t holdForTarget = item->holdDurationInMs >> 3;
uint32_t holdAbortTarget = item->abortButtonHoldDurationInMs >> 3;
while (true) {
uint32_t buttonsHold = 0;
VPADReadError vpad_error = VPAD_READ_UNINITIALIZED;
VPADStatus vpad_data;
VPADRead(VPAD_CHAN_0, &vpad_data, 1, &vpad_error);
if (vpad_error == VPAD_READ_SUCCESS) {
buttonsHold = vpad_data.hold;
}
if (buttonsHold == lastHold) {
if (buttonsHold != 0) {
holdFor++;
}
} else {
holdFor = 0;
}
lastHold = buttonsHold;
if (holdFor >= holdAbortTarget && lastHold == item->abortButton) {
break;
}
if (holdFor >= holdForTarget) {
item->value = lastHold;
break;
}
OSSleepTicks(OSMillisecondsToTicks(8));
}
}
void WUPSConfigItemButtonCombo_onButtonPressed(void *context, WUPSConfigButtons buttons) {
auto *item = (ConfigItemButtonCombo *) context;
if (item->state == BUTTON_COMBO_STATE_NONE) {
if ((buttons & WUPS_CONFIG_BUTTON_A) == WUPS_CONFIG_BUTTON_A) {
item->state = BUTTON_COMBO_STATE_PREPARE_FOR_HOLD;
}
}
}
bool WUPSConfigItemButtonCombo_isMovementAllowed(void *context) {
return true;
}
int32_t WUPSConfigItemButtonCombo_getCurrentValueSelectedDisplay(void *context, char *out_buf, int32_t out_size) {
auto *item = (ConfigItemButtonCombo *) context;
if (item->state == BUTTON_COMBO_STATE_PREPARE_FOR_HOLD || item->state == BUTTON_COMBO_STATE_WAIT_FOR_HOLD) {
if (item->state == BUTTON_COMBO_STATE_PREPARE_FOR_HOLD) {
item->state = BUTTON_COMBO_STATE_WAIT_FOR_HOLD;
snprintf(out_buf, out_size, "<Hold new combo for %dms; hold %s to abort>", item->holdDurationInMs, getButtonChar(item->abortButton).c_str());
return 0;
} else {
checkForHold(item);
item->state = BUTTON_COMBO_STATE_NONE;
}
}
snprintf(out_buf, out_size, "(Press \ue000 to change) %s", getComboAsString(item->value).c_str());
return 0;
}
void WUPSConfigItemButtonCombo_restoreDefault(void *context) {
auto *item = (ConfigItemButtonCombo *) context;
item->value = item->defaultValue;
}
void WUPSConfigItemButtonCombo_onSelected(void *context, bool isSelected) {
}
void WUPSConfigItemButtonCombo_onDelete(void *context) {
auto *item = (ConfigItemButtonCombo *) context;
if (item->configId) {
free(item->configId);
}
free(item);
}
extern "C" bool
WUPSConfigItemButtonComboAddToCategoryEx(WUPSConfigCategoryHandle cat, const char *configID, const char *displayName, uint32_t defaultComboInVPADButtons, uint32_t holdDurationInMs, VPADButtons abortButton, uint32_t abortButtonHoldDurationInMs, ButtonComboValueChangedCallback callback) {
if (cat == 0) {
return false;
}
auto *item = (ConfigItemButtonCombo *) malloc(sizeof(ConfigItemButtonCombo));
if (item == nullptr) {
OSReport("WUPSConfigItemButtonComboAddToCategoryEx: Failed to allocate memory for item data.\n");
return false;
}
if (configID != nullptr) {
item->configId = strdup(configID);
} else {
item->configId = nullptr;
}
item->abortButton = abortButton;
item->abortButtonHoldDurationInMs = abortButtonHoldDurationInMs;
item->holdDurationInMs = holdDurationInMs;
item->defaultValue = defaultComboInVPADButtons;
item->value = defaultComboInVPADButtons;
item->callback = (void *) callback;
item->state = BUTTON_COMBO_STATE_NONE;
WUPSConfigCallbacks_t callbacks = {
.getCurrentValueDisplay = &WUPSConfigItemButtonCombo_getCurrentValueDisplay,
.getCurrentValueSelectedDisplay = &WUPSConfigItemButtonCombo_getCurrentValueSelectedDisplay,
.onSelected = &WUPSConfigItemButtonCombo_onSelected,
.restoreDefault = &WUPSConfigItemButtonCombo_restoreDefault,
.isMovementAllowed = &WUPSConfigItemButtonCombo_isMovementAllowed,
.callCallback = &WUPSConfigItemButtonCombo_callCallback,
.onButtonPressed = &WUPSConfigItemButtonCombo_onButtonPressed,
.onDelete = &WUPSConfigItemButtonCombo_onDelete};
if (WUPSConfigItem_Create(&item->handle, configID, displayName, callbacks, item) < 0) {
OSReport("WUPSConfigItemButtonComboAddToCategoryEx: Failed to create config item.\n");
free(item);
return false;
}
if (WUPSConfigCategory_AddItem(cat, item->handle) < 0) {
OSReport("WUPSConfigItemButtonComboAddToCategoryEx: Failed to add item to category.\n");
WUPSConfigItem_Destroy(item->handle);
return false;
}
return true;
}
extern "C" bool
WUPSConfigItemButtonComboAddToCategory(WUPSConfigCategoryHandle cat, const char *configID, const char *displayName, uint32_t defaultComboInVPADButtons, ButtonComboValueChangedCallback callback) {
return WUPSConfigItemButtonComboAddToCategoryEx(cat, configID, displayName, defaultComboInVPADButtons, 2000, VPAD_BUTTON_B, 250, callback);
}

View File

@ -0,0 +1,43 @@
#include <stdint.h>
#include <vpad/input.h>
#include <wups.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum ButtonComboState {
BUTTON_COMBO_STATE_NONE,
BUTTON_COMBO_STATE_PREPARE_FOR_HOLD,
BUTTON_COMBO_STATE_WAIT_FOR_HOLD,
} ButtonComboState;
typedef struct ConfigItemButtonCombo {
char *configId;
WUPSConfigItemHandle handle;
uint32_t defaultValue;
uint32_t value;
uint32_t holdDurationInMs;
VPADButtons abortButton;
uint32_t abortButtonHoldDurationInMs;
void *callback;
ButtonComboState state;
} ConfigItemButtonCombo;
typedef void (*ButtonComboValueChangedCallback)(ConfigItemButtonCombo *item, uint32_t buttonComboInVPADButtons);
bool WUPSConfigItemButtonComboAddToCategory(WUPSConfigCategoryHandle cat, const char *configId, const char *displayName, uint32_t defaultComboInVPADButtons, ButtonComboValueChangedCallback callback);
bool WUPSConfigItemButtonComboAddToCategoryEx(WUPSConfigCategoryHandle cat, const char *configId, const char *displayName, uint32_t defaultComboInVPADButtons, uint32_t holdDurationInMs, VPADButtons abortButton, uint32_t abortButtonHoldDurationInMs, ButtonComboValueChangedCallback callback);
#define WUPSConfigItemButtonCombo_AddToCategoryHandled(__config__, __cat__, __configID__, __displayName__, __defaultComboInVPADButtons__, __callback__) \
do { \
if (!WUPSConfigItemButtonComboAddToCategory(__cat__, __configID__, __displayName__, __defaultComboInVPADButtons__, __callback__)) { \
WUPSConfig_Destroy(__config__); \
return 0; \
} \
} while (0)
#ifdef __cplusplus
}
#endif