Initial implementation of WUPSButtonComboAPI

This commit is contained in:
Maschell
2024-12-26 15:15:59 +01:00
parent dd6025a8d1
commit 1a42b79c4d
13 changed files with 1258 additions and 28 deletions

View File

@@ -29,7 +29,6 @@ WUPSConfigCategory WUPSConfigCategory::Create(std::string_view name) {
bool WUPSConfigCategory::add(WUPSConfigCategory &&cat, WUPSConfigAPIStatus &error) noexcept {
if (mHandle.handle == nullptr || cat.getHandle().handle == nullptr) {
OSReport("mHandle %08X item %08X\n", mHandle.handle, cat.getHandle().handle);
return false;
}
if ((error = WUPSConfigAPI_Category_AddCategory(mHandle, cat.getHandle())) != WUPSCONFIG_API_RESULT_SUCCESS) {
@@ -48,7 +47,6 @@ void WUPSConfigCategory::add(WUPSConfigCategory &&cat) {
bool WUPSConfigCategory::add(WUPSConfigItem &&item, WUPSConfigAPIStatus &error) noexcept {
if (mHandle.handle == nullptr || item.getHandle().handle == nullptr) {
OSReport("mHandle %08X item %08X\n", mHandle.handle, item.getHandle().handle);
error = WUPSCONFIG_API_RESULT_INVALID_ARGUMENT;
return false;
}

View File

@@ -0,0 +1,325 @@
#include <coreinit/debug.h>
#include <coreinit/thread.h>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <wups.h>
#include <wups/button_combo.h>
#include <wups/config/WUPSConfigItemButtonCombo.h>
namespace {
const char *getButtonChar(const WUPSButtonCombo_Buttons value) {
std::string combo;
if (value & WUPS_BUTTON_COMBO_BUTTON_A) {
return "\ue000";
}
if (value & WUPS_BUTTON_COMBO_BUTTON_B) {
return "\ue001";
}
if (value & WUPS_BUTTON_COMBO_BUTTON_X) {
return "\ue002";
}
if (value & WUPS_BUTTON_COMBO_BUTTON_Y) {
return "\ue003";
}
if (value & WUPS_BUTTON_COMBO_BUTTON_L) {
return "\ue083";
}
if (value & WUPS_BUTTON_COMBO_BUTTON_R) {
return "\ue084";
}
if (value & WUPS_BUTTON_COMBO_BUTTON_ZL) {
return "\ue085";
}
if (value & WUPS_BUTTON_COMBO_BUTTON_ZR) {
return "\ue086";
}
if (value & WUPS_BUTTON_COMBO_BUTTON_UP) {
return "\ue079";
}
if (value & WUPS_BUTTON_COMBO_BUTTON_DOWN) {
return "\ue07A";
}
if (value & WUPS_BUTTON_COMBO_BUTTON_LEFT) {
return "\ue07B";
}
if (value & WUPS_BUTTON_COMBO_BUTTON_RIGHT) {
return "\ue07C";
}
if (value & WUPS_BUTTON_COMBO_BUTTON_STICK_L) {
return "\ue081";
}
if (value & WUPS_BUTTON_COMBO_BUTTON_STICK_R) {
return "\ue082";
}
if (value & WUPS_BUTTON_COMBO_BUTTON_PLUS) {
return "\ue045";
}
if (value & WUPS_BUTTON_COMBO_BUTTON_MINUS) {
return "\ue046";
}
if (value & WUPS_BUTTON_COMBO_BUTTON_TV) {
return "\ue089";
}
if (value & WUPS_BUTTON_COMBO_BUTTON_RESERVED_BIT) {
return "\ue01E";
}
return "";
}
std::string getComboAsString(const uint32_t value) {
char comboString[60] = {};
for (uint32_t i = 0; i < 32; i++) {
uint32_t bitMask = 1 << i;
if (value & bitMask) {
auto val = getButtonChar(static_cast<WUPSButtonCombo_Buttons>(bitMask));
if (val[0] != '\0') {
strcat(comboString, val);
strcat(comboString, "+");
}
}
}
std::string res(comboString);
if (res.ends_with("+")) {
res.pop_back();
}
return res;
}
bool checkForHold(ConfigItemButtonCombo *item) {
const auto oldCombo = item->currentButtonCombo;
auto buttonCombo = static_cast<WUPSButtonCombo_Buttons>(0);
// This call is **blocking** it only returns if a button combo was detected or abort was triggered
WUPSButtonCombo_DetectButtonComboOptions options;
options.controllerMask = WUPS_BUTTON_COMBO_CONTROLLER_ALL;
options.abortButtonCombo = item->detectAbortButton;
options.holdAbortForInMs = item->detectAbortHoldButtonInMs;
options.holdComboForInMs = item->detectComboHoldDurationInMs;
if (const auto res = WUPSButtonComboAPI_DetectButtonCombo_Blocking(&options, &buttonCombo); res != WUPS_BUTTON_COMBO_ERROR_SUCCESS) {
OSReport("WUPSButtonComboAPI_DetectButtonCombo_Blocking returned %s\n", WUPSButtonComboAPI_GetStatusStr(res));
return false;
}
WUPSButtonCombo_ComboStatus status = WUPS_BUTTON_COMBO_COMBO_STATUS_INVALID_STATUS;
if (const auto res = WUPSButtonComboAPI_UpdateButtonCombo(item->comboHandle, buttonCombo, &status); res != WUPS_BUTTON_COMBO_ERROR_SUCCESS) {
OSReport("Failed to update combo info\n");
return false;
}
if (status != WUPS_BUTTON_COMBO_COMBO_STATUS_VALID) {
// (Try) to restore "old" button combo
if (WUPSButtonComboAPI_UpdateButtonCombo(item->comboHandle, oldCombo, &status) == WUPS_BUTTON_COMBO_ERROR_SUCCESS) {
OSReport("Failed to update combo info\n");
}
return false;
}
item->currentButtonCombo = buttonCombo;
return true;
}
int32_t getCurrentValueDisplayGeneric(void *context, bool isSelected, char *out_buf, int32_t out_size) {
auto *item = static_cast<ConfigItemButtonCombo *>(context);
WUPSButtonCombo_ComboStatus comboStatus = WUPS_BUTTON_COMBO_COMBO_STATUS_INVALID_STATUS;
if (const auto res = WUPSButtonComboAPI_GetButtonComboStatus(item->comboHandle, &comboStatus); res != WUPS_BUTTON_COMBO_ERROR_SUCCESS) {
OSReport("WUPSConfigItemButtonCombo_getCurrentValueDisplayGeneric: GetButtonComboStatus returned %d\n", WUPSButtonComboAPI_GetStatusStr(res));
}
switch (item->itemState) {
case WUPS_CONFIG_ITEM_BUTTON_COMBO_STATE_INVALID_HANDLE: {
snprintf(out_buf, out_size, "ERROR: Invalid combo handle");
return 0;
}
case WUPS_CONFIG_ITEM_BUTTON_COMBO_STATE_PREPARE_FOR_HOLD:
case WUPS_CONFIG_ITEM_BUTTON_COMBO_STATE_WAIT_FOR_HOLD: {
if (item->itemState == WUPS_CONFIG_ITEM_BUTTON_COMBO_STATE_PREPARE_FOR_HOLD) {
item->itemState = WUPS_CONFIG_ITEM_BUTTON_COMBO_STATE_WAIT_FOR_HOLD;
snprintf(out_buf, out_size, "<Hold new combo for %dms; hold %s to abort>", item->detectAbortHoldButtonInMs, getButtonChar(item->detectAbortButton));
return 0;
}
if (checkForHold(item)) {
item->itemState = WUPS_CONFIG_ITEM_BUTTON_COMBO_STATE_NONE;
} else {
item->itemState = WUPS_CONFIG_ITEM_BUTTON_COMBO_STATE_PREPARE_FOR_HOLD;
snprintf(out_buf, out_size, "ERROR: Conflict detected. Try again");
OSSleepTicks(OSMillisecondsToTicks(2000));
return 0;
}
break;
}
case WUPS_CONFIG_ITEM_BUTTON_COMBO_STATE_NONE:
break;
}
if (isSelected) {
snprintf(out_buf, out_size, "(Press \ue000 to change) %s%s", comboStatus == WUPS_BUTTON_COMBO_COMBO_STATUS_VALID ? "" : "[CONFLICT] ", getComboAsString(item->currentButtonCombo).c_str());
} else {
snprintf(out_buf, out_size, "%s%s", comboStatus == WUPS_BUTTON_COMBO_COMBO_STATUS_VALID ? "" : "[CONFLICT] ", getComboAsString(item->currentButtonCombo).c_str());
}
return 0;
}
} // namespace
static int32_t WUPSConfigItemButtonCombo_getCurrentValueDisplay(void *context, char *out_buf, int32_t out_size) {
return getCurrentValueDisplayGeneric(context, false, out_buf, out_size);
}
static void WUPSConfigItemButtonCombo_onCloseCallback(void *context) {
auto *item = static_cast<ConfigItemButtonCombo *>(context);
if (item->comboComboAtCreation != item->currentButtonCombo && item->valueChangedCallback != nullptr) {
reinterpret_cast<ButtonComboValueChangedCallback>(item->valueChangedCallback)(item, item->currentButtonCombo);
}
}
static void WUPSConfigItemButtonCombo_onInput(void *context, WUPSConfigSimplePadData input) {
auto *item = static_cast<ConfigItemButtonCombo *>(context);
if (item->itemState == WUPS_CONFIG_ITEM_BUTTON_COMBO_STATE_NONE) {
if ((input.buttons_d & WUPS_CONFIG_BUTTON_A) == WUPS_CONFIG_BUTTON_A) {
item->itemState = WUPS_CONFIG_ITEM_BUTTON_COMBO_STATE_PREPARE_FOR_HOLD;
}
}
}
static int32_t
WUPSConfigItemButtonCombo_getCurrentValueSelectedDisplay(void *context, char *out_buf, int32_t out_size) {
return getCurrentValueDisplayGeneric(context, true, out_buf, out_size);
}
static void WUPSConfigItemButtonCombo_restoreDefault(void *context) {
auto *item = static_cast<ConfigItemButtonCombo *>(context);
if (const auto res = WUPSButtonComboAPI_UpdateButtonCombo(item->comboHandle, item->defaultButtonCombo, nullptr); res != WUPS_BUTTON_COMBO_ERROR_SUCCESS) {
OSReport("WUPSConfigItemButtonCombo_restoreDefault: Failed to update combo info\n");
return;
}
item->currentButtonCombo = item->defaultButtonCombo;
}
static bool WUPSConfigItemButtonCombo_isMovementAllowed(void *context) {
const auto *item = static_cast<ConfigItemButtonCombo *>(context);
return item->itemState != WUPS_CONFIG_ITEM_BUTTON_COMBO_STATE_PREPARE_FOR_HOLD && item->itemState != WUPS_CONFIG_ITEM_BUTTON_COMBO_STATE_WAIT_FOR_HOLD;
}
static void WUPSConfigItemButtonCombo_Cleanup(ConfigItemButtonCombo *item) {
if (!item) {
return;
}
free(item->identifier);
free(item);
}
static void WUPSConfigItemButtonCombo_onDelete(void *context) {
WUPSConfigItemButtonCombo_Cleanup(static_cast<ConfigItemButtonCombo *>(context));
}
WUPSConfigAPIStatus
WUPSConfigItemButtonCombo_CreateEx(const char *identifier,
const char *displayName,
const WUPSButtonCombo_Buttons defaultComboInWUPSButtonComboButtons, const WUPSButtonCombo_ComboHandle comboHandle,
const uint32_t detectHoldDurationInMs, const WUPSButtonCombo_Buttons detectAbortButtonCombo, const uint32_t detectAbortHoldButtonInMs,
const ButtonComboValueChangedCallback callback,
WUPSConfigItemHandle *outItemHandle) {
if (outItemHandle == nullptr) {
return WUPSCONFIG_API_RESULT_INVALID_ARGUMENT;
}
auto *item = static_cast<ConfigItemButtonCombo *>(malloc(sizeof(ConfigItemButtonCombo)));
if (item == nullptr) {
OSReport("WUPSConfigItemButtonCombo_CreateEx: Failed to allocate memory for item data.\n");
return WUPSCONFIG_API_RESULT_INVALID_ARGUMENT;
}
if (identifier != nullptr) {
item->identifier = strdup(identifier);
} else {
item->identifier = nullptr;
}
item->comboHandle = comboHandle;
item->defaultButtonCombo = static_cast<WUPSButtonCombo_Buttons>(defaultComboInWUPSButtonComboButtons);
item->currentButtonCombo = static_cast<WUPSButtonCombo_Buttons>(0);
item->comboComboAtCreation = defaultComboInWUPSButtonComboButtons;
item->detectComboHoldDurationInMs = detectHoldDurationInMs;
item->detectAbortButton = detectAbortButtonCombo;
item->detectAbortHoldButtonInMs = detectAbortHoldButtonInMs;
item->valueChangedCallback = reinterpret_cast<void *>(callback);
item->intern.conflictMsgShownForXFrames = 0;
item->itemState = WUPS_CONFIG_ITEM_BUTTON_COMBO_STATE_NONE;
WUPSButtonCombo_ButtonComboInfoEx comboOptions = {};
if (const WUPSButtonCombo_Error comboErr = WUPSButtonComboAPI_GetButtonComboInfoEx(comboHandle, &comboOptions); comboErr == WUPS_BUTTON_COMBO_ERROR_SUCCESS) {
item->comboComboAtCreation = comboOptions.basicCombo.combo;
item->currentButtonCombo = comboOptions.basicCombo.combo;
} else {
OSReport("WUPSButtonComboAPI_GetButtonComboInfo failed %s\n", WUPSButtonComboAPI_GetStatusStr(comboErr));
item->itemState = WUPS_CONFIG_ITEM_BUTTON_COMBO_STATE_INVALID_HANDLE;
}
constexpr WUPSConfigAPIItemCallbacksV2 callbacks = {
.getCurrentValueDisplay = &WUPSConfigItemButtonCombo_getCurrentValueDisplay,
.getCurrentValueSelectedDisplay = &WUPSConfigItemButtonCombo_getCurrentValueSelectedDisplay,
.onSelected = nullptr,
.restoreDefault = &WUPSConfigItemButtonCombo_restoreDefault,
.isMovementAllowed = &WUPSConfigItemButtonCombo_isMovementAllowed,
.onCloseCallback = &WUPSConfigItemButtonCombo_onCloseCallback,
.onInput = &WUPSConfigItemButtonCombo_onInput,
.onInputEx = nullptr,
.onDelete = &WUPSConfigItemButtonCombo_onDelete,
};
const WUPSConfigAPIItemOptionsV2 options = {
.displayName = displayName,
.context = item,
.callbacks = callbacks,
};
if (const WUPSConfigAPIStatus err = WUPSConfigAPI_Item_Create(options, &item->itemHandle); err != WUPSCONFIG_API_RESULT_SUCCESS) {
OSReport("WUPSConfigItemButtonCombo_tAddToCategoryEx: Failed to create config item.\n");
WUPSConfigItemButtonCombo_Cleanup(item);
return err;
}
*outItemHandle = item->itemHandle;
return WUPSCONFIG_API_RESULT_SUCCESS;
}
WUPSConfigAPIStatus
WUPSConfigItemButtonCombo_AddToCategoryEx(const WUPSConfigCategoryHandle cat,
const char *identifier, const char *displayName,
const WUPSButtonCombo_Buttons defaultComboInWUPSButtonComboButtons, const WUPSButtonCombo_ComboHandle comboHandle,
const uint32_t detectHoldDurationInMs, const WUPSButtonCombo_Buttons detectAbortButtonCombo, const uint32_t detectAbortHoldButtonInMs,
const ButtonComboValueChangedCallback callback) {
WUPSConfigItemHandle itemHandle;
WUPSConfigAPIStatus res;
if ((res = WUPSConfigItemButtonCombo_CreateEx(identifier,
displayName,
defaultComboInWUPSButtonComboButtons, comboHandle,
detectHoldDurationInMs, detectAbortButtonCombo, detectAbortHoldButtonInMs,
callback, &itemHandle)) != WUPSCONFIG_API_RESULT_SUCCESS) {
return res;
}
if ((res = WUPSConfigAPI_Category_AddItem(cat, itemHandle)) != WUPSCONFIG_API_RESULT_SUCCESS) {
WUPSConfigAPI_Item_Destroy(itemHandle);
return res;
}
return WUPSCONFIG_API_RESULT_SUCCESS;
}
WUPSConfigAPIStatus
WUPSConfigItemButtonCombo_AddToCategory(const WUPSConfigCategoryHandle cat,
const char *identifier, const char *displayName,
const WUPSButtonCombo_Buttons defaultComboInWUPSButtonComboButtons, const WUPSButtonCombo_ComboHandle comboHandle,
const ButtonComboValueChangedCallback callback) {
return WUPSConfigItemButtonCombo_AddToCategoryEx(cat, identifier, displayName,
defaultComboInWUPSButtonComboButtons, comboHandle,
2000, WUPS_BUTTON_COMBO_BUTTON_B, 250,
callback);
}

View File

@@ -0,0 +1,54 @@
#include <stdexcept>
#include <wups/config/WUPSConfigItemButtonCombo.h>
#include <wups/config_api.h>
std::optional<WUPSConfigItemButtonCombo> WUPSConfigItemButtonCombo::CreateEx(const std::optional<std::string> &identifier,
const std::string_view displayName,
const WUPSButtonCombo_Buttons defaultComboInWUPSButtonComboButtons, const WUPSButtonCombo_ComboHandle comboHandle,
const uint32_t detectHoldDurationInMs, const WUPSButtonCombo_Buttons detectAbortButtonCombo, const uint32_t detectAbortHoldButtonInMs,
const ButtonComboValueChangedCallback callback,
WUPSConfigAPIStatus &err) noexcept {
WUPSConfigItemHandle itemHandle;
if ((err = WUPSConfigItemButtonCombo_CreateEx(identifier ? identifier->data() : nullptr,
displayName.data(),
defaultComboInWUPSButtonComboButtons, comboHandle,
detectHoldDurationInMs, detectAbortButtonCombo, detectAbortHoldButtonInMs,
callback,
&itemHandle)) != WUPSCONFIG_API_RESULT_SUCCESS) {
return std::nullopt;
}
return WUPSConfigItemButtonCombo(itemHandle);
}
WUPSConfigItemButtonCombo WUPSConfigItemButtonCombo::CreateEx(const std::optional<std::string> &identifier,
const std::string_view displayName,
const WUPSButtonCombo_Buttons defaultComboInWUPSButtonComboButtons, const WUPSButtonCombo_ComboHandle comboHandle,
const uint32_t detectHoldDurationInMs, const WUPSButtonCombo_Buttons detectAbortButtonCombo, const uint32_t detectAbortHoldButtonInMs,
const ButtonComboValueChangedCallback callback) {
WUPSConfigAPIStatus err;
auto result = CreateEx(identifier, displayName, defaultComboInWUPSButtonComboButtons, comboHandle, detectHoldDurationInMs, detectAbortButtonCombo, detectAbortHoldButtonInMs, callback, err);
if (!result) {
throw std::runtime_error(std::string("Failed to create WUPSConfigItemButtonCombo: ").append(WUPSConfigAPI_GetStatusStr(err)));
}
return std::move(*result);
}
std::optional<WUPSConfigItemButtonCombo> WUPSConfigItemButtonCombo::Create(const std::optional<std::string> &identifier,
const std::string_view displayName,
const WUPSButtonCombo_Buttons defaultComboInWUPSButtonComboButtons, const WUPSButtonCombo_ComboHandle comboHandle,
const ButtonComboValueChangedCallback callback,
WUPSConfigAPIStatus &err) noexcept {
return CreateEx(identifier, displayName, defaultComboInWUPSButtonComboButtons, comboHandle, 2000, WUPS_BUTTON_COMBO_BUTTON_B, 250, callback, err);
}
WUPSConfigItemButtonCombo WUPSConfigItemButtonCombo::Create(const std::optional<std::string> &identifier,
const std::string_view displayName,
const WUPSButtonCombo_Buttons defaultComboInWUPSButtonComboButtons, const WUPSButtonCombo_ComboHandle comboHandle,
const ButtonComboValueChangedCallback callback) {
WUPSConfigAPIStatus err = WUPSCONFIG_API_RESULT_UNKNOWN_ERROR;
auto res = Create(identifier, displayName, defaultComboInWUPSButtonComboButtons, comboHandle, callback, err);
if (!res) {
throw std::runtime_error(std::string("Failed to create WUPSConfigItemButtonCombo: ").append(WUPSConfigAPI_GetStatusStr(err)));
}
return std::move(*res);
}

View File

@@ -0,0 +1,314 @@
#include <cstdint>
#include <wups/button_combo.h>
#include <wups/button_combo_internal.h>
struct wups_internal_button_combo_functions_t {
void *identifier = nullptr;
WUPSButtonCombo_AddButtonComboFunction add_button_combo_function_ptr = nullptr;
WUPSButtonCombo_RemoveButtonComboFunction remove_button_combo_function_ptr = nullptr;
WUPSButtonCombo_GetButtonComboStatusFunction get_button_combo_status_function_ptr = nullptr;
WUPSButtonCombo_UpdateButtonComboMetaFunction update_button_combo_meta_function_ptr = nullptr;
WUPSButtonCombo_UpdateButtonComboCallbackFunction update_button_combo_callback_function_ptr = nullptr;
WUPSButtonCombo_UpdateControllerMaskFunction update_controller_mask_function_ptr = nullptr;
WUPSButtonCombo_UpdateButtonComboFunction update_button_combo_function_ptr = nullptr;
WUPSButtonCombo_UpdateHoldDurationFunction update_hold_duration_function_ptr = nullptr;
WUPSButtonCombo_GetButtonComboMetaFunction get_button_combo_meta_function_ptr = nullptr;
WUPSButtonCombo_GetButtonComboCallbackFunction get_button_combo_callback_function_ptr = nullptr;
WUPSButtonCombo_GetButtonComboInfoExFunction get_button_combo_info_ex_function_ptr = nullptr;
WUPSButtonCombo_CheckComboAvailableFunction check_button_combo_available_function_ptr = nullptr;
WUPSButtonCombo_DetectButtonComboBlockingFunction detect_button_combo_blocking_function_ptr = nullptr;
};
static wups_internal_button_combo_functions_t __internal_functions = {};
extern "C" WUPSButtonCombo_Error WUPSButtonComboAPI_InitInternal(const wups_loader_init_button_combo_args_t &args) {
if (args.version > WUPS_BUTTON_COMBO_CUR_API_VERSION) {
__internal_functions = {};
return WUPS_BUTTON_COMBO_ERROR_INTERNAL_INVALID_VERSION;
}
__internal_functions.identifier = args.identifier;
__internal_functions.add_button_combo_function_ptr = args.add_button_combo_function_ptr;
__internal_functions.remove_button_combo_function_ptr = args.remove_button_combo_function_ptr;
__internal_functions.get_button_combo_status_function_ptr = args.get_button_combo_status_function_ptr;
__internal_functions.update_button_combo_meta_function_ptr = args.update_button_combo_meta_function_ptr;
__internal_functions.update_button_combo_callback_function_ptr = args.update_button_combo_callback_function_ptr;
__internal_functions.update_controller_mask_function_ptr = args.update_controller_mask_function_ptr;
__internal_functions.update_button_combo_function_ptr = args.update_button_combo_function_ptr;
__internal_functions.update_hold_duration_function_ptr = args.update_hold_duration_function_ptr;
__internal_functions.get_button_combo_meta_function_ptr = args.get_button_combo_meta_function_ptr;
__internal_functions.get_button_combo_callback_function_ptr = args.get_button_combo_callback_function_ptr;
__internal_functions.get_button_combo_info_ex_function_ptr = args.get_button_combo_info_ex_function_ptr;
__internal_functions.check_button_combo_available_function_ptr = args.check_button_combo_available_function_ptr;
__internal_functions.detect_button_combo_blocking_function_ptr = args.detect_button_combo_blocking_function_ptr;
return WUPS_BUTTON_COMBO_ERROR_SUCCESS;
}
const char *WUPSButtonComboAPI_GetStatusStr(const WUPSButtonCombo_Error status) {
switch (status) {
case WUPS_BUTTON_COMBO_ERROR_SUCCESS:
return "WUPS_BUTTON_COMBO_ERROR_SUCCESS";
case WUPS_BUTTON_COMBO_ERROR_INVALID_ARGS:
return "WUPS_BUTTON_COMBO_ERROR_INVALID_ARGS";
case WUPS_BUTTON_COMBO_ERROR_MALLOC_FAILED:
return "WUPS_BUTTON_COMBO_ERROR_MALLOC_FAILED";
case WUPS_BUTTON_COMBO_ERROR_NOT_FOUND:
return "WUPS_BUTTON_COMBO_ERROR_NOT_FOUND";
case WUPS_BUTTON_COMBO_ERROR_INTERNAL_NOT_INITIALIZED:
return "WUPS_BUTTON_COMBO_ERROR_INTERNAL_NOT_INITIALIZED";
case WUPS_BUTTON_COMBO_ERROR_INTERNAL_INVALID_VERSION:
return "WUPS_BUTTON_COMBO_ERROR_INTERNAL_INVALID_VERSION";
case WUPS_BUTTON_COMBO_ERROR_UNKNOWN_ERROR:
return "WUPS_BUTTON_COMBO_ERROR_UNKNOWN_ERROR";
case WUPS_BUTTON_COMBO_ERROR_ABORTED:
return "WUPS_BUTTON_COMBO_ERROR_ABORTED";
}
return "WUPS_BUTTON_COMBO_ERROR_UNKNOWN_ERROR";
}
static WUPSButtonCombo_Error WUPSButtonComboAPI_AddButtonComboPressEx(const char *label,
const WUPSButtonCombo_Buttons combo,
const WUPSButtonCombo_ComboCallback callback,
void *context,
const bool observer,
WUPSButtonCombo_ComboHandle *outHandle,
WUPSButtonCombo_ComboStatus *outStatus) {
WUPSButtonCombo_ComboOptions options = {};
options.metaOptions.label = label;
options.callbackOptions = {.callback = callback, .context = context};
options.buttonComboOptions.type = observer ? WUPS_BUTTON_COMBO_COMBO_TYPE_PRESS_DOWN_OBSERVER : WUPS_BUTTON_COMBO_COMBO_TYPE_PRESS_DOWN;
options.buttonComboOptions.basicCombo.combo = combo;
options.buttonComboOptions.basicCombo.controllerMask = WUPS_BUTTON_COMBO_CONTROLLER_ALL;
return WUPSButtonComboAPI_AddButtonCombo(&options, outHandle, outStatus);
}
WUPSButtonCombo_Error WUPSButtonComboAPI_AddButtonComboPressDown(const char *label,
const WUPSButtonCombo_Buttons combo,
const WUPSButtonCombo_ComboCallback callback,
void *context,
WUPSButtonCombo_ComboHandle *outHandle,
WUPSButtonCombo_ComboStatus *outStatus) {
return WUPSButtonComboAPI_AddButtonComboPressEx(label, combo, callback, context, false, outHandle, outStatus);
}
WUPSButtonCombo_Error WUPSButtonComboAPI_AddButtonComboPressDownObserver(const char *label,
const WUPSButtonCombo_Buttons combo,
const WUPSButtonCombo_ComboCallback callback,
void *context,
WUPSButtonCombo_ComboHandle *outHandle,
WUPSButtonCombo_ComboStatus *outStatus) {
return WUPSButtonComboAPI_AddButtonComboPressEx(label, combo, callback, context, true, outHandle, outStatus);
}
static WUPSButtonCombo_Error WUPSButtonComboAPI_AddButtonComboHoldEx(const char *label,
const WUPSButtonCombo_Buttons combo,
const uint32_t holdDurationInFrames,
const WUPSButtonCombo_ComboCallback callback,
void *context,
const bool observer,
WUPSButtonCombo_ComboHandle *outHandle,
WUPSButtonCombo_ComboStatus *outStatus) {
WUPSButtonCombo_ComboOptions options = {};
options.metaOptions.label = label;
options.callbackOptions = {.callback = callback, .context = context};
options.buttonComboOptions.type = observer ? WUPS_BUTTON_COMBO_COMBO_TYPE_HOLD_OBSERVER : WUPS_BUTTON_COMBO_COMBO_TYPE_HOLD;
options.buttonComboOptions.basicCombo.combo = combo;
options.buttonComboOptions.basicCombo.controllerMask = WUPS_BUTTON_COMBO_CONTROLLER_ALL;
options.buttonComboOptions.optionalHoldForXFrames = holdDurationInFrames;
return WUPSButtonComboAPI_AddButtonCombo(&options, outHandle, outStatus);
}
WUPSButtonCombo_Error WUPSButtonComboAPI_AddButtonComboHold(const char *label,
const WUPSButtonCombo_Buttons combo,
const uint32_t holdDurationInFrames,
const WUPSButtonCombo_ComboCallback callback,
void *context,
WUPSButtonCombo_ComboHandle *outHandle,
WUPSButtonCombo_ComboStatus *outStatus) {
return WUPSButtonComboAPI_AddButtonComboHoldEx(label, combo, holdDurationInFrames, callback, context, false, outHandle, outStatus);
}
WUPSButtonCombo_Error WUPSButtonComboAPI_AddButtonComboHoldObserver(const char *label,
const WUPSButtonCombo_Buttons combo,
const uint32_t holdDurationInFrames,
const WUPSButtonCombo_ComboCallback callback,
void *context,
WUPSButtonCombo_ComboHandle *outHandle,
WUPSButtonCombo_ComboStatus *outStatus) {
return WUPSButtonComboAPI_AddButtonComboHoldEx(label, combo, holdDurationInFrames, callback, context, true, outHandle, outStatus);
}
WUPSButtonCombo_Error WUPSButtonComboAPI_AddButtonCombo(const WUPSButtonCombo_ComboOptions *options,
WUPSButtonCombo_ComboHandle *outHandle,
WUPSButtonCombo_ComboStatus *outStatus) {
if (__internal_functions.add_button_combo_function_ptr == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INTERNAL_NOT_INITIALIZED;
}
if (__internal_functions.identifier == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INTERNAL_NOT_INITIALIZED;
}
if (options == nullptr || outHandle == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INVALID_ARGS;
}
return __internal_functions.add_button_combo_function_ptr(__internal_functions.identifier, options, outHandle, outStatus);
}
WUPSButtonCombo_Error WUPSButtonComboAPI_RemoveButtonCombo(const WUPSButtonCombo_ComboHandle handle) {
if (__internal_functions.remove_button_combo_function_ptr == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INTERNAL_NOT_INITIALIZED;
}
if (__internal_functions.identifier == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INTERNAL_NOT_INITIALIZED;
}
return __internal_functions.remove_button_combo_function_ptr(__internal_functions.identifier, handle);
}
WUPSButtonCombo_Error WUPSButtonComboAPI_GetButtonComboStatus(const WUPSButtonCombo_ComboHandle handle,
WUPSButtonCombo_ComboStatus *outStatus) {
if (__internal_functions.get_button_combo_status_function_ptr == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INTERNAL_NOT_INITIALIZED;
}
if (__internal_functions.identifier == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INTERNAL_NOT_INITIALIZED;
}
if (outStatus == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INVALID_ARGS;
}
return __internal_functions.get_button_combo_status_function_ptr(__internal_functions.identifier, handle, outStatus);
}
WUPSButtonCombo_Error WUPSButtonComboAPI_UpdateButtonComboMeta(const WUPSButtonCombo_ComboHandle handle,
const WUPSButtonCombo_MetaOptions *metaOptions) {
if (__internal_functions.update_button_combo_meta_function_ptr == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INTERNAL_NOT_INITIALIZED;
}
if (__internal_functions.identifier == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INTERNAL_NOT_INITIALIZED;
}
if (metaOptions == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INVALID_ARGS;
}
return __internal_functions.update_button_combo_meta_function_ptr(__internal_functions.identifier, handle, metaOptions);
}
WUPSButtonCombo_Error WUPSButtonComboAPI_UpdateButtonComboCallback(const WUPSButtonCombo_ComboHandle handle,
const WUPSButtonCombo_CallbackOptions *callbackOptions) {
if (__internal_functions.update_button_combo_callback_function_ptr == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INTERNAL_NOT_INITIALIZED;
}
if (__internal_functions.identifier == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INTERNAL_NOT_INITIALIZED;
}
if (callbackOptions == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INVALID_ARGS;
}
return __internal_functions.update_button_combo_callback_function_ptr(__internal_functions.identifier, handle, callbackOptions);
}
WUPSButtonCombo_Error WUPSButtonComboAPI_UpdateControllerMask(const WUPSButtonCombo_ComboHandle handle,
const WUPSButtonCombo_ControllerTypes controllerMask,
WUPSButtonCombo_ComboStatus *outStatus) {
if (__internal_functions.update_controller_mask_function_ptr == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INTERNAL_NOT_INITIALIZED;
}
if (__internal_functions.identifier == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INTERNAL_NOT_INITIALIZED;
}
return __internal_functions.update_controller_mask_function_ptr(__internal_functions.identifier, handle, controllerMask, outStatus);
}
WUPSButtonCombo_Error WUPSButtonComboAPI_UpdateButtonCombo(const WUPSButtonCombo_ComboHandle handle,
const WUPSButtonCombo_Buttons combo,
WUPSButtonCombo_ComboStatus *outStatus) {
if (__internal_functions.update_button_combo_function_ptr == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INTERNAL_NOT_INITIALIZED;
}
if (__internal_functions.identifier == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INTERNAL_NOT_INITIALIZED;
}
return __internal_functions.update_button_combo_function_ptr(__internal_functions.identifier, handle, combo, outStatus);
}
WUPSButtonCombo_Error WUPSButtonComboAPI_UpdateHoldDuration(const WUPSButtonCombo_ComboHandle handle,
const uint32_t holdDurationInFrames) {
if (__internal_functions.update_hold_duration_function_ptr == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INTERNAL_NOT_INITIALIZED;
}
if (__internal_functions.identifier == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INTERNAL_NOT_INITIALIZED;
}
return __internal_functions.update_hold_duration_function_ptr(__internal_functions.identifier, handle, holdDurationInFrames);
}
WUPSButtonCombo_Error WUPSButtonComboAPI_GetButtonComboMeta(const WUPSButtonCombo_ComboHandle handle,
WUPSButtonCombo_MetaOptionsOut *outOptions) {
if (__internal_functions.get_button_combo_meta_function_ptr == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INTERNAL_NOT_INITIALIZED;
}
if (__internal_functions.identifier == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INTERNAL_NOT_INITIALIZED;
}
if (outOptions == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INVALID_ARGS;
}
return __internal_functions.get_button_combo_meta_function_ptr(__internal_functions.identifier, handle, outOptions);
}
WUPSButtonCombo_Error WUPSButtonComboAPI_GetButtonComboCallback(const WUPSButtonCombo_ComboHandle handle,
WUPSButtonCombo_CallbackOptions *outOptions) {
if (__internal_functions.get_button_combo_callback_function_ptr == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INTERNAL_NOT_INITIALIZED;
}
if (__internal_functions.identifier == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INTERNAL_NOT_INITIALIZED;
}
if (outOptions == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INVALID_ARGS;
}
return __internal_functions.get_button_combo_callback_function_ptr(__internal_functions.identifier, handle, outOptions);
}
WUPSButtonCombo_Error WUPSButtonComboAPI_GetButtonComboInfoEx(const WUPSButtonCombo_ComboHandle handle,
WUPSButtonCombo_ButtonComboInfoEx *outOptions) {
if (__internal_functions.get_button_combo_info_ex_function_ptr == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INTERNAL_NOT_INITIALIZED;
}
if (__internal_functions.identifier == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INTERNAL_NOT_INITIALIZED;
}
if (outOptions == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INVALID_ARGS;
}
return __internal_functions.get_button_combo_info_ex_function_ptr(__internal_functions.identifier, handle, outOptions);
}
WUPSButtonCombo_Error WUPSButtonComboAPI_CheckComboAvailable(const WUPSButtonCombo_ButtonComboOptions *options,
WUPSButtonCombo_ComboStatus *outStatus) {
if (__internal_functions.check_button_combo_available_function_ptr == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INTERNAL_NOT_INITIALIZED;
}
if (__internal_functions.identifier == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INTERNAL_NOT_INITIALIZED;
}
if (options == nullptr || outStatus == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INVALID_ARGS;
}
return __internal_functions.check_button_combo_available_function_ptr(__internal_functions.identifier, options, outStatus);
}
WUPSButtonCombo_Error WUPSButtonComboAPI_DetectButtonCombo_Blocking(const WUPSButtonCombo_DetectButtonComboOptions *options,
WUPSButtonCombo_Buttons *outButtons) {
if (__internal_functions.detect_button_combo_blocking_function_ptr == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INTERNAL_NOT_INITIALIZED;
}
if (__internal_functions.identifier == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INTERNAL_NOT_INITIALIZED;
}
if (options == nullptr || outButtons == nullptr) {
return WUPS_BUTTON_COMBO_ERROR_INVALID_ARGS;
}
return __internal_functions.detect_button_combo_blocking_function_ptr(__internal_functions.identifier, options, outButtons);
}