Initial implementation of WUPSButtonComboAPI

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

299
include/wups/button_combo.h Normal file
View File

@ -0,0 +1,299 @@
#pragma once
#include <stdint.h>
#include <wut_types.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum WUPSButtonCombo_Buttons {
//! The A button.
WUPS_BUTTON_COMBO_BUTTON_A = 0x8000,
//! The B button.
WUPS_BUTTON_COMBO_BUTTON_B = 0x4000,
//! The X button.
WUPS_BUTTON_COMBO_BUTTON_X = 0x2000,
//! The Y button.
WUPS_BUTTON_COMBO_BUTTON_Y = 0x1000,
//! The left button of the D-pad.
WUPS_BUTTON_COMBO_BUTTON_LEFT = 0x0800,
//! The right button of the D-pad.
WUPS_BUTTON_COMBO_BUTTON_RIGHT = 0x0400,
//! The up button of the D-pad.
WUPS_BUTTON_COMBO_BUTTON_UP = 0x0200,
//! The down button of the D-pad.
WUPS_BUTTON_COMBO_BUTTON_DOWN = 0x0100,
//! The ZL button.
WUPS_BUTTON_COMBO_BUTTON_ZL = 0x0080,
//! The ZR button.
WUPS_BUTTON_COMBO_BUTTON_ZR = 0x0040,
//! The L button.
WUPS_BUTTON_COMBO_BUTTON_L = 0x0020,
//! The R button.
WUPS_BUTTON_COMBO_BUTTON_R = 0x0010,
//! The + button.
WUPS_BUTTON_COMBO_BUTTON_PLUS = 0x0008,
//! The - button.
WUPS_BUTTON_COMBO_BUTTON_MINUS = 0x0004,
//! The right stick button.
WUPS_BUTTON_COMBO_BUTTON_STICK_R = 0x00020000,
//! The left stick button.
WUPS_BUTTON_COMBO_BUTTON_STICK_L = 0x00040000,
//! The TV button.
WUPS_BUTTON_COMBO_BUTTON_TV = 0x00010000,
//! The reserved bit
WUPS_BUTTON_COMBO_BUTTON_RESERVED_BIT = 0x80000,
} WUPSButtonCombo_Buttons;
WUT_ENUM_BITMASK_TYPE(WUPSButtonCombo_Buttons);
typedef enum WUPSButtonCombo_ControllerTypes {
WUPS_BUTTON_COMBO_CONTROLLER_NONE = 0,
WUPS_BUTTON_COMBO_CONTROLLER_VPAD_0 = 1 << 0,
WUPS_BUTTON_COMBO_CONTROLLER_VPAD_1 = 1 << 1,
WUPS_BUTTON_COMBO_CONTROLLER_WPAD_0 = 1 << 2,
WUPS_BUTTON_COMBO_CONTROLLER_WPAD_1 = 1 << 3,
WUPS_BUTTON_COMBO_CONTROLLER_WPAD_2 = 1 << 4,
WUPS_BUTTON_COMBO_CONTROLLER_WPAD_3 = 1 << 5,
WUPS_BUTTON_COMBO_CONTROLLER_WPAD_4 = 1 << 6,
WUPS_BUTTON_COMBO_CONTROLLER_WPAD_5 = 1 << 7,
WUPS_BUTTON_COMBO_CONTROLLER_WPAD_6 = 1 << 8,
WUPS_BUTTON_COMBO_CONTROLLER_VPAD = WUPS_BUTTON_COMBO_CONTROLLER_VPAD_0 | WUPS_BUTTON_COMBO_CONTROLLER_VPAD_1,
WUPS_BUTTON_COMBO_CONTROLLER_WPAD = (WUPS_BUTTON_COMBO_CONTROLLER_WPAD_0 |
WUPS_BUTTON_COMBO_CONTROLLER_WPAD_1 |
WUPS_BUTTON_COMBO_CONTROLLER_WPAD_2 |
WUPS_BUTTON_COMBO_CONTROLLER_WPAD_3 |
WUPS_BUTTON_COMBO_CONTROLLER_WPAD_4 |
WUPS_BUTTON_COMBO_CONTROLLER_WPAD_5 |
WUPS_BUTTON_COMBO_CONTROLLER_WPAD_6),
WUPS_BUTTON_COMBO_CONTROLLER_ALL = WUPS_BUTTON_COMBO_CONTROLLER_VPAD | WUPS_BUTTON_COMBO_CONTROLLER_WPAD,
} WUPSButtonCombo_ControllerTypes;
WUT_ENUM_BITMASK_TYPE(WUPSButtonCombo_ControllerTypes);
typedef enum WUPSButtonCombo_ComboType {
WUPS_BUTTON_COMBO_COMBO_TYPE_INVALID = 0,
WUPS_BUTTON_COMBO_COMBO_TYPE_HOLD = 1, // Does check for conflicts
WUPS_BUTTON_COMBO_COMBO_TYPE_PRESS_DOWN = 2, // Does check for conflicts
WUPS_BUTTON_COMBO_COMBO_TYPE_HOLD_OBSERVER = 3, // Does not check for conflicts
WUPS_BUTTON_COMBO_COMBO_TYPE_PRESS_DOWN_OBSERVER = 4, // Does not check for conflicts
} WUPSButtonCombo_ComboType;
typedef enum WUPSButtonCombo_ComboStatus {
WUPS_BUTTON_COMBO_COMBO_STATUS_INVALID_STATUS = 0,
WUPS_BUTTON_COMBO_COMBO_STATUS_VALID = 1,
WUPS_BUTTON_COMBO_COMBO_STATUS_CONFLICT = 2,
} WUPSButtonCombo_ComboStatus;
/**
* @enum WUPSButtonComboError
* @brief Represents error codes returned by storage API functions.
*/
typedef enum {
WUPS_BUTTON_COMBO_ERROR_SUCCESS = 0, /**< Success. */
WUPS_BUTTON_COMBO_ERROR_INVALID_ARGS = -0x01, /**< Invalid arguments passed to the function. */
WUPS_BUTTON_COMBO_ERROR_MALLOC_FAILED = -0x02, /**< Memory allocation failed. */
WUPS_BUTTON_COMBO_ERROR_NOT_FOUND = -0x03, /**< Not found. */
WUPS_BUTTON_COMBO_ERROR_ABORTED = -0x04, /**< Not found. */
WUPS_BUTTON_COMBO_ERROR_INTERNAL_NOT_INITIALIZED = -0xF0, /**< Library not initialized properly. */
WUPS_BUTTON_COMBO_ERROR_INTERNAL_INVALID_VERSION = -0xF1, /**< Invalid API version. */
WUPS_BUTTON_COMBO_ERROR_UNKNOWN_ERROR = -0x100 /**< Unknown error. */
} WUPSButtonCombo_Error;
typedef struct WUPSButtonCombo_ComboHandle {
void *handle;
#ifdef __cplusplus
WUPSButtonCombo_ComboHandle() {
handle = nullptr;
}
explicit WUPSButtonCombo_ComboHandle(void *handle) : handle(handle) {}
bool operator==(const WUPSButtonCombo_ComboHandle other) const {
return handle == other.handle;
}
bool operator==(const void *other) const {
return handle == other;
}
#endif
} WUPSButtonCombo_ComboHandle;
typedef void (*WUPSButtonCombo_ComboCallback)(WUPSButtonCombo_ComboHandle handle, void *context);
typedef struct WUPSButtonCombo_MetaOptions {
const char *label;
} WUPSButtonCombo_MetaOptions;
typedef struct WUPSButtonCombo_MetaOptionsOut {
char *labelBuffer;
uint32_t labelBufferLength;
} WUPSButtonCombo_MetaOptionsOut;
typedef struct WUPSButtonCombo_CallbackOptions {
WUPSButtonCombo_ComboCallback callback;
void *context;
} WUPSButtonCombo_CallbackOptions;
typedef struct WUPSButtonCombo_ButtonComboOptions {
WUPSButtonCombo_ControllerTypes controllerMask;
WUPSButtonCombo_Buttons combo;
} WUPSButtonCombo_ButtonComboOptions;
typedef struct WUPSButtonCombo_ButtonComboInfoEx {
WUPSButtonCombo_ComboType type;
WUPSButtonCombo_ButtonComboOptions basicCombo;
uint32_t optionalHoldForXFrames;
} WUPSButtonCombo_ButtonComboInfoEx;
typedef struct WUPSButtonCombo_ComboOptions {
WUPSButtonCombo_MetaOptions metaOptions;
WUPSButtonCombo_CallbackOptions callbackOptions;
WUPSButtonCombo_ButtonComboInfoEx buttonComboOptions;
} WUPSButtonCombo_ComboOptions;
typedef struct WUPSButtonCombo_DetectButtonComboOptions {
WUPSButtonCombo_ControllerTypes controllerMask;
uint32_t holdComboForInMs;
uint32_t holdAbortForInMs;
WUPSButtonCombo_Buttons abortButtonCombo;
} WUPSButtonCombo_DetectButtonComboOptions;
/**
* @brief Get a string representation of the specified button_combo status.
*
* This function returns a string representation of the provided button_combo status.
*
* @param status The button_combo status to get the string representation for.
* @return A pointer to a string describing the provided button_combo status.
**/
const char *WUPSButtonComboAPI_GetStatusStr(WUPSButtonCombo_Error status);
/**
* @brief Adds a button combo which triggers a callback if a certain button combination is pressed on any controller.
*
* Registers a unique button combination which will trigger a callback if the combo is pressed down **on any connected controller** and the button combo is valid
*
* A press down is only detecting while pressing down buttons. Releasing a button will never trigger the callback.
* For example if the combo is "L+R+X" but you hold down "L+R+Y", press then "X" and release "Y" the combo won't be triggered.
*
* Conflict management:
* The button combination is only active if this function returns WUPS_BUTTON_COMBO_ERROR_SUCCESS and outStatus is WUPS_BUTTON_COMBO_COMBO_STATUS_VALID.
*
* If any other (valid) button combination overlaps with the button combo, the outStatus WUPS_BUTTON_COMBO_COMBO_STATUS_CONFLICT and the callback will not be triggered
* even if the combination is pressed.
*
* Even if the button combination would be unique and valid (due to the change or removal of other combos), the status won't update itself.
* To resolve a WUPS_BUTTON_COMBO_COMBO_STATUS_CONFLICT combo state you **always** have to the combo information via WUPSButtonComboAPI_UpdateButtonComboInfo or WUPSButtonComboAPI_UpdateButtonComboSimple.
*
* Conflict example: It's not possible to add any new valid button combo containing "L+R" (e.g. "X+L+R"), if there already is a button combination "L+R".
* Furthermore, it's also not possible to add a "L" or "R" combo if there already is a button combination "L+R".
*
* @param label Label of this button combo
* @param combo Combination which should be checked
* @param callbackOptions Information about the callbacks that will be called if the combo is triggered
* @param outHandle The handle of the combo will be stored here. Must not be nullptr.
* @param outStatus The status of the combo will be stored here. Only if the status is WUPS_BUTTON_COMBO_COMBO_STATUS_VALID the combo is valid. Must not be nullptr.
* @return
**/
WUPSButtonCombo_Error WUPSButtonComboAPI_AddButtonComboPressDown(const char *label,
WUPSButtonCombo_Buttons combo,
WUPSButtonCombo_ComboCallback callback,
void *context,
WUPSButtonCombo_ComboHandle *outHandle,
WUPSButtonCombo_ComboStatus *outStatus);
WUPSButtonCombo_Error WUPSButtonComboAPI_AddButtonComboPressDownObserver(const char *label,
WUPSButtonCombo_Buttons combo,
WUPSButtonCombo_ComboCallback callback,
void *context,
WUPSButtonCombo_ComboHandle *outHandle,
WUPSButtonCombo_ComboStatus *outStatus);
/**
* @brief Adds a button combo which triggers a callback if a certain button combination was hold for X frames on any controller.
*
* Registers a unique button combination which will trigger a callback if the combo is held for a certain amount of frames **on any connected controller** and the button combo is valid.
*
* The callback is triggered if the given button combination has been held down for the given number of frames (frame rate might vary from game to game).
*
* Conflict management:
* The button combination is only active if this function returns WUPS_BUTTON_COMBO_ERROR_SUCCESS and outStatus is WUPS_BUTTON_COMBO_COMBO_STATUS_VALID.
*
* If any other (valid) button combination overlaps with the button combo, the outStatus WUPS_BUTTON_COMBO_COMBO_STATUS_CONFLICT and the callback will not be triggered
* even if the combination is pressed.
*
* Even if the button combination would be unique and valid (due to the change or removal of other combos), the status won't update itself.
* To resolve a WUPS_BUTTON_COMBO_COMBO_STATUS_CONFLICT combo state you **always** have to the combo information via WUPSButtonComboAPI_UpdateButtonComboInfo or WUPSButtonComboAPI_UpdateButtonComboSimple.
*
* Conflict example: It's not possible to add any new valid button combo containing "L+R" (e.g. "X+L+R"), if there already is a button combination "L+R".
* Furthermore, it's also not possible to add a "L" or "R" combo if there already is a button combination "L+R".
*
* @param label Label of this button combo
* @param combo Combination which should be checked
* @param holdDurationInFrames
* @param callbackOptions Information about the callbacks that will be called if the combo is triggered
* @param outHandle The handle of the combo will be stored here. Must not be nullptr.
* @param outStatus The status of the combo will be stored here. Only if the status is WUPS_BUTTON_COMBO_COMBO_STATUS_VALID the combo is valid. Must not be nullptr.
* @return
**/
WUPSButtonCombo_Error WUPSButtonComboAPI_AddButtonComboHold(const char *label,
WUPSButtonCombo_Buttons combo,
uint32_t holdDurationInFrames,
WUPSButtonCombo_ComboCallback callback,
void *context,
WUPSButtonCombo_ComboHandle *outHandle,
WUPSButtonCombo_ComboStatus *outStatus);
WUPSButtonCombo_Error WUPSButtonComboAPI_AddButtonComboHoldObserver(const char *label,
WUPSButtonCombo_Buttons combo,
uint32_t holdDurationInFrames,
WUPSButtonCombo_ComboCallback callback,
void *context,
WUPSButtonCombo_ComboHandle *outHandle,
WUPSButtonCombo_ComboStatus *outStatus);
WUPSButtonCombo_Error WUPSButtonComboAPI_AddButtonCombo(const WUPSButtonCombo_ComboOptions *options,
WUPSButtonCombo_ComboHandle *outHandle,
WUPSButtonCombo_ComboStatus *outStatus);
/**
* Removes a button combo for the given handle.
*/
WUPSButtonCombo_Error WUPSButtonComboAPI_RemoveButtonCombo(WUPSButtonCombo_ComboHandle handle);
/**
* Returns the combo status for the given handle
*/
WUPSButtonCombo_Error WUPSButtonComboAPI_GetButtonComboStatus(WUPSButtonCombo_ComboHandle handle,
WUPSButtonCombo_ComboStatus *outStatus);
WUPSButtonCombo_Error WUPSButtonComboAPI_UpdateButtonComboMeta(WUPSButtonCombo_ComboHandle handle,
const WUPSButtonCombo_MetaOptions *metaOptions);
WUPSButtonCombo_Error WUPSButtonComboAPI_UpdateButtonComboCallback(WUPSButtonCombo_ComboHandle handle,
const WUPSButtonCombo_CallbackOptions *callbackOptions);
WUPSButtonCombo_Error WUPSButtonComboAPI_UpdateControllerMask(WUPSButtonCombo_ComboHandle handle,
WUPSButtonCombo_ControllerTypes controllerMask,
WUPSButtonCombo_ComboStatus *outStatus);
WUPSButtonCombo_Error WUPSButtonComboAPI_UpdateButtonCombo(WUPSButtonCombo_ComboHandle handle,
WUPSButtonCombo_Buttons combo,
WUPSButtonCombo_ComboStatus *outStatus);
WUPSButtonCombo_Error WUPSButtonComboAPI_UpdateHoldDuration(WUPSButtonCombo_ComboHandle handle,
uint32_t holdDurationInFrames);
WUPSButtonCombo_Error WUPSButtonComboAPI_GetButtonComboMeta(WUPSButtonCombo_ComboHandle handle,
WUPSButtonCombo_MetaOptionsOut *outOptions);
WUPSButtonCombo_Error WUPSButtonComboAPI_GetButtonComboCallback(WUPSButtonCombo_ComboHandle handle,
WUPSButtonCombo_CallbackOptions *outOptions);
WUPSButtonCombo_Error WUPSButtonComboAPI_GetButtonComboInfoEx(WUPSButtonCombo_ComboHandle handle,
WUPSButtonCombo_ButtonComboInfoEx *outOptions);
WUPSButtonCombo_Error WUPSButtonComboAPI_CheckComboAvailable(const WUPSButtonCombo_ButtonComboOptions *options,
WUPSButtonCombo_ComboStatus *outStatus);
WUPSButtonCombo_Error WUPSButtonComboAPI_DetectButtonCombo_Blocking(const WUPSButtonCombo_DetectButtonComboOptions *options,
WUPSButtonCombo_Buttons *outButtons);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,141 @@
#pragma once
#include <wups/button_combo.h>
/**
* @typedef WUPSButtonCombo_AddButtonComboFunction
* @brief Type alias for the function pointer to add a button combo. For internal usage only.
*/
typedef WUPSButtonCombo_Error (*WUPSButtonCombo_AddButtonComboFunction)(void *identifier,
const WUPSButtonCombo_ComboOptions *options,
WUPSButtonCombo_ComboHandle *outHandle,
WUPSButtonCombo_ComboStatus *outStatus);
/**
* @typedef WUPSButtonCombo_RemoveButtonComboFunction
* @brief Type alias for the function pointer to remove a button combo. For internal usage only.
*/
typedef WUPSButtonCombo_Error (*WUPSButtonCombo_RemoveButtonComboFunction)(void *identifier,
WUPSButtonCombo_ComboHandle handle);
/**
* @typedef WUPSButtonCombo_GetButtonComboStatusFunction
* @brief Type alias for the function pointer to check the status of a button combo. For internal usage only.
*/
typedef WUPSButtonCombo_Error (*WUPSButtonCombo_GetButtonComboStatusFunction)(void *identifier,
WUPSButtonCombo_ComboHandle handle,
WUPSButtonCombo_ComboStatus *outStatus);
/**
* @typedef WUPSButtonCombo_UpdateButtonComboMetaFunction
* @brief Type alias for the function pointer to update the meta data of a button combo. For internal usage only.
*/
typedef WUPSButtonCombo_Error (*WUPSButtonCombo_UpdateButtonComboMetaFunction)(void *identifier,
WUPSButtonCombo_ComboHandle handle,
const WUPSButtonCombo_MetaOptions *metaOptions);
/**
* @typedef WUPSButtonCombo_UpdateButtonComboMetaFunction
* @brief Type alias for the function pointer to update the meta data of a button combo. For internal usage only.
*/
typedef WUPSButtonCombo_Error (*WUPSButtonCombo_UpdateButtonComboCallbackFunction)(void *identifier,
WUPSButtonCombo_ComboHandle handle,
const WUPSButtonCombo_CallbackOptions *callbackOptions);
/**
* @typedef WUPSButtonCombo_UpdateButtonComboMetaFunction
* @brief Type alias for the function pointer to update the controller mask of a button combo. For internal usage only.
*/
typedef WUPSButtonCombo_Error (*WUPSButtonCombo_UpdateControllerMaskFunction)(void *identifier,
WUPSButtonCombo_ComboHandle handle,
WUPSButtonCombo_ControllerTypes controllerMask,
WUPSButtonCombo_ComboStatus *outStatus);
/**
* @typedef WUPSButtonCombo_UpdateButtonCallbackFunction
* @brief Type alias for the function pointer to update the callback data of a button combo. For internal usage only.
*/
typedef WUPSButtonCombo_Error (*WUPSButtonCombo_UpdateButtonComboFunction)(void *identifier,
WUPSButtonCombo_ComboHandle handle,
WUPSButtonCombo_Buttons combo,
WUPSButtonCombo_ComboStatus *outStatus);
/**
* @typedef WUPSButtonCombo_UpdateButtonComboInfoFunction
* @brief Type alias for the function pointer to update the info data of a button combo. For internal usage only.
*/
typedef WUPSButtonCombo_Error (*WUPSButtonCombo_UpdateHoldDurationFunction)(void *identifier,
WUPSButtonCombo_ComboHandle handle,
uint32_t holdDurationInFrames);
/**
* @typedef WUPSButtonCombo_GetButtonComboMetaFunction
* @brief Type alias for the function pointer to get the meta data of a button combo. For internal usage only.
*/
typedef WUPSButtonCombo_Error (*WUPSButtonCombo_GetButtonComboMetaFunction)(void *identifier,
WUPSButtonCombo_ComboHandle handle,
WUPSButtonCombo_MetaOptionsOut *outOptions);
/**
* @typedef WUPSButtonCombo_GetButtonComboCallbackFunction
* @brief Type alias for the function pointer to get the callback data of a button combo. For internal usage only.
*/
typedef WUPSButtonCombo_Error (*WUPSButtonCombo_GetButtonComboCallbackFunction)(void *identifier,
WUPSButtonCombo_ComboHandle handle,
WUPSButtonCombo_CallbackOptions *outOptions);
/**
* @typedef WUPSButtonCombo_GetButtonComboInfoFunction
* @brief Type alias for the function pointer to get the info data of a button combo. For internal usage only.
*/
typedef WUPSButtonCombo_Error (*WUPSButtonCombo_GetButtonComboInfoExFunction)(void *identifier,
WUPSButtonCombo_ComboHandle handle,
WUPSButtonCombo_ButtonComboInfoEx *outOptions);
/**
* @typedef WUPSButtonCombo_CheckComboAvailableFunction
* @brief Type alias for the function pointer check if a button combo is available. For internal usage only.
*/
typedef WUPSButtonCombo_Error (*WUPSButtonCombo_CheckComboAvailableFunction)(void *identifier,
const WUPSButtonCombo_ButtonComboOptions *options,
WUPSButtonCombo_ComboStatus *outStatus);
/**
* @typedef WUPSButtonCombo_CheckComboAvailableFunction
* @brief Type alias for the function pointer to detect a button combo. For internal usage only.
*/
typedef WUPSButtonCombo_Error (*WUPSButtonCombo_DetectButtonComboBlockingFunction)(void *identifier,
const WUPSButtonCombo_DetectButtonComboOptions *options,
WUPSButtonCombo_Buttons *outButtons);
/**
* @typedef WUPS_BUTTON_COMBO_API_VERSION
* @brief Type alias for the API version. For internal usage only.
*/
typedef uint32_t WUPS_BUTTON_COMBO_API_VERSION;
/**
* @def WUPS_BUTTON_COMBO_CUR_API_VERSION
* @brief Current version of the button_combo API. For internal usage only.
*/
#define WUPS_BUTTON_COMBO_CUR_API_VERSION 0x01
/**
* @struct wups_loader_init_button_combo_args_t_
* @brief Structure containing initialization arguments for the button_combo API. For internal usage only.
*/
typedef struct wups_loader_init_button_combo_args_t_ {
WUPS_BUTTON_COMBO_API_VERSION version; /**< API version. */
void *identifier; /**< Unique identifier */
WUPSButtonCombo_AddButtonComboFunction add_button_combo_function_ptr; /**< AddButtonCombo function pointer. */
WUPSButtonCombo_RemoveButtonComboFunction remove_button_combo_function_ptr; /**< RemoveButtonCombo function pointer. */
WUPSButtonCombo_GetButtonComboStatusFunction get_button_combo_status_function_ptr; /**< GetButtonComboStatus function pointer. */
WUPSButtonCombo_UpdateButtonComboMetaFunction update_button_combo_meta_function_ptr; /**< UpdateButtonComboMeta function pointer. */
WUPSButtonCombo_UpdateButtonComboCallbackFunction update_button_combo_callback_function_ptr; /**< UpdateButtonComboCallback function pointer. */
WUPSButtonCombo_UpdateControllerMaskFunction update_controller_mask_function_ptr; /**< UpdateButtonComboExFunction function pointer. */
WUPSButtonCombo_UpdateButtonComboFunction update_button_combo_function_ptr; /**< UpdateButtonComboExFunction function pointer. */
WUPSButtonCombo_UpdateHoldDurationFunction update_hold_duration_function_ptr; /**< UpdateButtonComboExFunction function pointer. */
WUPSButtonCombo_GetButtonComboMetaFunction get_button_combo_meta_function_ptr; /**< GetButtonComboMeta function pointer. */
WUPSButtonCombo_GetButtonComboCallbackFunction get_button_combo_callback_function_ptr; /**< GetButtonComboCallback function pointer. */
WUPSButtonCombo_GetButtonComboInfoExFunction get_button_combo_info_ex_function_ptr; /**< GetButtonComboEx function pointer. */
WUPSButtonCombo_CheckComboAvailableFunction check_button_combo_available_function_ptr; /**< CheckComboAvailable function pointer. */
WUPSButtonCombo_DetectButtonComboBlockingFunction detect_button_combo_blocking_function_ptr; /**< DetectButtonCombo_Blocking function pointer. */
} wups_loader_init_button_combo_args_t;

View File

@ -25,15 +25,6 @@
#pragma once
#include <dirent.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#ifdef __cplusplus
extern "C" {
#endif

View File

@ -42,6 +42,7 @@ typedef enum WUPS_CONFIG_SIMPLE_INPUT {
WUPS_CONFIG_BUTTON_PLUS = (1 << 14),
WUPS_CONFIG_BUTTON_MINUS = (1 << 15),
} WUPS_CONFIG_SIMPLE_INPUT;
WUT_ENUM_BITMASK_TYPE(WUPS_CONFIG_SIMPLE_INPUT);
typedef struct {
WUPS_CONFIG_SIMPLE_INPUT buttons_h;

View File

@ -3,11 +3,10 @@
#ifdef __cplusplus
#include "wups/config.h"
#include <coreinit/debug.h>
class WUPSConfigItem {
protected:
explicit WUPSConfigItem(WUPSConfigItemHandle itemHandle) : mHandle(itemHandle) {
explicit WUPSConfigItem(const WUPSConfigItemHandle itemHandle) : mHandle(itemHandle) {
}
public:

View File

@ -0,0 +1,99 @@
#pragma once
#include <stdint.h>
#include <wups/button_combo.h>
#include <wups/config.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum ConfigItemButtonCombo_State {
WUPS_CONFIG_ITEM_BUTTON_COMBO_STATE_NONE,
WUPS_CONFIG_ITEM_BUTTON_COMBO_STATE_PREPARE_FOR_HOLD,
WUPS_CONFIG_ITEM_BUTTON_COMBO_STATE_WAIT_FOR_HOLD,
WUPS_CONFIG_ITEM_BUTTON_COMBO_STATE_INVALID_HANDLE,
} ConfigItemButtonCombo_State;
typedef struct ConfigItemButtonCombo {
char *identifier;
WUPSConfigItemHandle itemHandle;
ConfigItemButtonCombo_State itemState;
WUPSButtonCombo_ComboHandle comboHandle;
WUPSButtonCombo_Buttons defaultButtonCombo;
WUPSButtonCombo_Buttons currentButtonCombo;
WUPSButtonCombo_Buttons comboComboAtCreation;
uint32_t detectComboHoldDurationInMs;
WUPSButtonCombo_Buttons detectAbortButton;
uint32_t detectAbortHoldButtonInMs;
void *valueChangedCallback;
struct {
uint32_t conflictMsgShownForXFrames;
} intern;
} ConfigItemButtonCombo;
typedef void (*ButtonComboValueChangedCallback)(ConfigItemButtonCombo *item, uint32_t buttonComboInWUPSButtonComboButtons);
WUPSConfigAPIStatus
WUPSConfigItemButtonCombo_CreateEx(const char *identifier,
const char *displayName,
WUPSButtonCombo_Buttons defaultComboInWUPSButtonComboButtons, WUPSButtonCombo_ComboHandle comboHandle,
uint32_t detectHoldDurationInMs, WUPSButtonCombo_Buttons detectAbortButtonCombo, uint32_t detectAbortHoldButtonInMs,
ButtonComboValueChangedCallback callback,
WUPSConfigItemHandle *outItemHandle);
WUPSConfigAPIStatus
WUPSConfigItemButtonCombo_AddToCategoryEx(WUPSConfigCategoryHandle cat,
const char *identifier, const char *displayName,
WUPSButtonCombo_Buttons defaultComboInWUPSButtonComboButtons, WUPSButtonCombo_ComboHandle comboHandle,
uint32_t detectHoldDurationInMs, WUPSButtonCombo_Buttons detectAbortButtonCombo, uint32_t detectAbortHoldButtonInMs,
ButtonComboValueChangedCallback callback);
WUPSConfigAPIStatus
WUPSConfigItemButtonCombo_AddToCategory(WUPSConfigCategoryHandle cat,
const char *identifier, const char *displayName,
WUPSButtonCombo_Buttons defaultComboInWUPSButtonComboButtons, WUPSButtonCombo_ComboHandle comboHandle,
ButtonComboValueChangedCallback callback);
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
#include <optional>
#include <string>
#include <wups/config/WUPSConfigItem.h>
class WUPSConfigItemButtonCombo : public WUPSConfigItem {
public:
static std::optional<WUPSConfigItemButtonCombo> CreateEx(const std::optional<std::string> &identifier,
std::string_view displayName,
WUPSButtonCombo_Buttons defaultComboInWUPSButtonComboButtons, WUPSButtonCombo_ComboHandle comboHandle,
uint32_t detectHoldDurationInMs, WUPSButtonCombo_Buttons detectAbortButtonCombo, uint32_t detectAbortHoldButtonInMs,
ButtonComboValueChangedCallback callback,
WUPSConfigAPIStatus &err) noexcept;
static WUPSConfigItemButtonCombo CreateEx(const std::optional<std::string> &identifier,
std::string_view displayName,
WUPSButtonCombo_Buttons defaultComboInWUPSButtonComboButtons, WUPSButtonCombo_ComboHandle comboHandle,
uint32_t detectHoldDurationInMs, WUPSButtonCombo_Buttons detectAbortButtonCombo, uint32_t detectAbortHoldButtonInMs,
ButtonComboValueChangedCallback callback);
static std::optional<WUPSConfigItemButtonCombo> Create(const std::optional<std::string> &identifier,
std::string_view displayName,
WUPSButtonCombo_Buttons defaultComboInWUPSButtonComboButtons, WUPSButtonCombo_ComboHandle comboHandle,
ButtonComboValueChangedCallback callback,
WUPSConfigAPIStatus &err) noexcept;
static WUPSConfigItemButtonCombo Create(const std::optional<std::string> &identifier,
std::string_view displayName,
WUPSButtonCombo_Buttons defaultComboInWUPSButtonComboButtons, WUPSButtonCombo_ComboHandle comboHandle,
ButtonComboValueChangedCallback callback);
private:
explicit WUPSConfigItemButtonCombo(const WUPSConfigItemHandle itemHandle) : WUPSConfigItem(itemHandle) {
}
};
#endif

View File

@ -1,9 +1,6 @@
#pragma once
#include "config.h"
#include "config/WUPSConfigCategory.h"
#include "config/WUPSConfigItem.h"
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
@ -79,7 +76,7 @@ WUPSConfigAPIStatus WUPSConfigAPI_Category_CreateEx(WUPSConfigAPICreateCategoryO
* a different category
*/
static inline WUPSConfigAPIStatus WUPSConfigAPI_Category_Create(WUPSConfigAPICreateCategoryOptionsV1 options, WUPSConfigCategoryHandle *out) {
WUPSConfigAPICreateCategoryOptions optionsWrapper = {
const WUPSConfigAPICreateCategoryOptions optionsWrapper = {
.version = WUPS_API_CATEGORY_OPTION_VERSION_V1,
.data = {.v1 = options},
};
@ -173,7 +170,7 @@ WUPSConfigAPIStatus WUPSConfigAPI_Item_CreateEx(WUPSConfigAPICreateItemOptions o
* a category
*/
static inline WUPSConfigAPIStatus WUPSConfigAPI_Item_Create(WUPSConfigAPIItemOptionsV2 options, WUPSConfigItemHandle *out) {
WUPSConfigAPICreateItemOptions itemOptions = {
const WUPSConfigAPICreateItemOptions itemOptions = {
.version = WUPS_API_ITEM_OPTION_VERSION_V2,
.data = {.v2 = options},
};

View File

@ -17,6 +17,9 @@
#pragma once
#include "common.h"
#include <wups/button_combo_internal.h>
#include <wups/config.h>
#include <wups/storage.h>
#ifdef __cplusplus
extern "C" {
@ -56,8 +59,9 @@ typedef enum wups_loader_hook_type_t {
WUPS_LOADER_HOOK_APPLICATION_REQUESTS_EXIT, /* Called when an application wants to exit */
WUPS_LOADER_HOOK_APPLICATION_ENDS, /* Called when an application ends */
WUPS_LOADER_HOOK_INIT_STORAGE, /* Only for internal usage */
WUPS_LOADER_HOOK_INIT_CONFIG, /* Only for internal usage */
WUPS_LOADER_HOOK_INIT_STORAGE, /* Only for internal usage */
WUPS_LOADER_HOOK_INIT_CONFIG, /* Only for internal usage */
WUPS_LOADER_HOOK_INIT_BUTTON_COMBO, /* Only for internal usage */
} wups_loader_hook_type_t;
typedef struct wups_loader_hook_t {
@ -123,10 +127,18 @@ typedef struct wups_loader_hook_t {
#define WUPS_INIT_CONFIG_FUNCTIONS() \
__EXTERN_C_MACRO WUPSConfigAPIStatus WUPSConfigAPI_InitLibrary_Internal(wups_loader_init_config_args_t args); \
void wups_init_config_functions(wups_loader_init_config_args_t); \
WUPSConfigAPIStatus wups_init_config_functions(wups_loader_init_config_args_t); \
WUPS_HOOK_EX(WUPS_LOADER_HOOK_INIT_CONFIG, wups_init_config_functions); \
void wups_init_config_functions(wups_loader_init_config_args_t args) { \
WUPSConfigAPI_InitLibrary_Internal(args); \
WUPSConfigAPIStatus wups_init_config_functions(wups_loader_init_config_args_t args) { \
return WUPSConfigAPI_InitLibrary_Internal(args); \
}
#define WUPS_INIT_BUTTON_COMBO_FUNCTIONS() \
__EXTERN_C_MACRO WUPSButtonCombo_Error WUPSButtonComboAPI_InitInternal(wups_loader_init_button_combo_args_t args); \
WUPSButtonCombo_Error wups_init_button_combo_functions(wups_loader_init_button_combo_args_t); \
WUPS_HOOK_EX(WUPS_LOADER_HOOK_INIT_BUTTON_COMBO, wups_init_button_combo_functions); \
WUPSButtonCombo_Error wups_init_button_combo_functions(wups_loader_init_button_combo_args_t args) { \
return WUPSButtonComboAPI_InitInternal(args); \
}
#define WUPS_USE_WUT_MALLOC() \

View File

@ -49,6 +49,7 @@ extern "C" {
WUPS___INIT_WRAPPER(); \
WUPS___FINI_WRAPPER(); \
WUPS_INIT_CONFIG_FUNCTIONS(); \
WUPS_INIT_BUTTON_COMBO_FUNCTIONS(); \
WUPS_META(buildtimestamp, __DATE__ " " __TIME__); \
WUPS_SECTION("meta") \
const char wups_meta_plugin_name[] = __plugin_name; \
@ -61,11 +62,10 @@ extern "C" {
"Function \"wut_get_thread_specific\" returned unexpected value.\n" \
"Please check linking order (expected \"-lwups -lwut\")";
#define WUPS_PLUGIN_AUTHOR(x) WUPS_META(author, x)
#define WUPS_PLUGIN_VERSION(x) WUPS_META(version, x)
#define WUPS_PLUGIN_LICENSE(x) WUPS_META(license, x)
#define WUPS_PLUGIN_DESCRIPTION(x) WUPS_META(description, x)
#define WUPS_PLUGIN_CONFIG_REVISION(x) WUPS_META(config_revision, #x)
#define WUPS_PLUGIN_AUTHOR(x) WUPS_META(author, x)
#define WUPS_PLUGIN_VERSION(x) WUPS_META(version, x)
#define WUPS_PLUGIN_LICENSE(x) WUPS_META(license, x)
#define WUPS_PLUGIN_DESCRIPTION(x) WUPS_META(description, x)
#ifdef __cplusplus
}

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);
}