WIP on supporting both mouse/keyboard and gamepad bindings at the same time

This commit is contained in:
UnknownShadow200 2023-09-01 18:45:14 +10:00
parent 577ba9bf82
commit 55316623a7
8 changed files with 74 additions and 71 deletions

View File

@ -820,8 +820,8 @@ static void LocalPlayer_InputSet(int key, cc_bool pressed) {
struct HacksComp* hacks = &LocalPlayer_Instance.Hacks;
if (pressed && !hacks->Enabled) return;
if (key == KeyBinds[KEYBIND_SPEED]) hacks->Speeding = pressed;
if (key == KeyBinds[KEYBIND_HALF_SPEED]) hacks->HalfSpeeding = pressed;
if (KeyBind_Claims(KEYBIND_SPEED, key)) hacks->Speeding = pressed;
if (KeyBind_Claims(KEYBIND_HALF_SPEED, key)) hacks->HalfSpeeding = pressed;
}
static void LocalPlayer_InputDown(void* obj, int key, cc_bool was) {

View File

@ -321,7 +321,9 @@ void Pointer_SetPosition(int idx, int x, int y) {
/*########################################################################################################################*
*---------------------------------------------------------Keybinds--------------------------------------------------------*
*#########################################################################################################################*/
cc_uint8 KeyBinds[KEYBIND_COUNT];
cc_uint8 KeyBinds_Gamepad[KEYBIND_COUNT];
cc_uint8 KeyBinds_Normal[KEYBIND_COUNT];
/* TODO find a better way than this. maybe alternative keybinds? */
const cc_uint8 KeyBind_GamepadDefaults[KEYBIND_COUNT] = {
CCPAD_UP, CCPAD_DOWN, CCPAD_LEFT, CCPAD_RIGHT, /* Movement */
@ -368,24 +370,26 @@ static const char* const keybindNames[KEYBIND_COUNT] = {
"HotbarLeft", "HotbarRight"
};
cc_bool KeyBind_IsPressed(KeyBind binding) { return Input.Pressed[KeyBinds[binding]]; }
cc_bool KeyBind_IsPressed(KeyBind binding) {
return Input.Pressed[KeyBinds_Normal[binding]] ||
Input.Pressed[KeyBinds_Gamepad[binding]];
}
static void KeyBind_Load(void) {
static void KeyBind_Load(const char* prefix, cc_uint8* keybinds, const cc_uint8* defaults) {
cc_string name; char nameBuffer[STRING_SIZE + 1];
const cc_uint8* defaults;
int mapping;
int i;
int mapping, i;
defaults = KeyBind_GetDefaults();
String_InitArray_NT(name, nameBuffer);
for (i = 0; i < KEYBIND_COUNT; i++)
{
name.length = 0;
String_Format1(&name, "key-%c", keybindNames[i]);
String_Format1(&name, prefix, keybindNames[i]);
name.buffer[name.length] = '\0';
mapping = Options_GetEnum(name.buffer, defaults[i], storageNames, INPUT_COUNT);
if (mapping != CCKEY_ESCAPE) KeyBinds[i] = mapping;
if (mapping == CCKEY_ESCAPE) mapping = defaults[i];
keybinds[i] = mapping;
}
}
@ -402,15 +406,8 @@ void KeyBind_Set(KeyBind binding, int key) {
/* Initialises and loads key bindings from options */
static void KeyBind_Init(void) {
const cc_uint8* defaults;
int i;
defaults = KeyBind_GetDefaults();
for (i = 0; i < KEYBIND_COUNT; i++)
{
KeyBinds[i] = defaults[i];
}
KeyBind_Load();
KeyBind_Load("key-%c", KeyBinds_Normal, KeyBind_NormalDefaults);
KeyBind_Load("pad-%c", KeyBinds_Gamepad, KeyBind_GamepadDefaults);
}
@ -904,13 +901,13 @@ static void InputHandler_CheckZoomFov(void* obj) {
static cc_bool HandleBlockKey(int key) {
if (Gui.InputGrab) return false;
if (key == KeyBinds[KEYBIND_DELETE_BLOCK]) {
if (KeyBind_Claims(KEYBIND_DELETE_BLOCK, key)) {
MouseStatePress(MOUSE_LEFT);
InputHandler_DeleteBlock();
} else if (key == KeyBinds[KEYBIND_PLACE_BLOCK]) {
} else if (KeyBind_Claims(KEYBIND_PLACE_BLOCK, key)) {
MouseStatePress(MOUSE_RIGHT);
InputHandler_PlaceBlock();
} else if (key == KeyBinds[KEYBIND_PICK_BLOCK]) {
} else if (KeyBind_Claims(KEYBIND_PICK_BLOCK, key)) {
MouseStatePress(MOUSE_MIDDLE);
InputHandler_PickBlock();
} else {
@ -920,32 +917,32 @@ static cc_bool HandleBlockKey(int key) {
}
static cc_bool HandleNonClassicKey(int key) {
if (key == KeyBinds[KEYBIND_HIDE_GUI]) {
if (KeyBind_Claims(KEYBIND_HIDE_GUI, key)) {
Game_HideGui = !Game_HideGui;
} else if (key == KeyBinds[KEYBIND_SMOOTH_CAMERA]) {
} else if (KeyBind_Claims(KEYBIND_SMOOTH_CAMERA, key)) {
InputHandler_Toggle(key, &Camera.Smooth,
" &eSmooth camera is &aenabled",
" &eSmooth camera is &cdisabled");
} else if (key == KeyBinds[KEYBIND_AXIS_LINES]) {
} else if (KeyBind_Claims(KEYBIND_AXIS_LINES, key)) {
InputHandler_Toggle(key, &AxisLinesRenderer_Enabled,
" &eAxis lines (&4X&e, &2Y&e, &1Z&e) now show",
" &eAxis lines no longer show");
} else if (key == KeyBinds[KEYBIND_AUTOROTATE]) {
} else if (KeyBind_Claims(KEYBIND_AUTOROTATE, key)) {
InputHandler_Toggle(key, &AutoRotate_Enabled,
" &eAuto rotate is &aenabled",
" &eAuto rotate is &cdisabled");
} else if (key == KeyBinds[KEYBIND_THIRD_PERSON]) {
} else if (KeyBind_Claims(KEYBIND_THIRD_PERSON, key)) {
Camera_CycleActive();
} else if (key == KeyBinds[KEYBIND_DROP_BLOCK]) {
} else if (KeyBind_Claims(KEYBIND_DROP_BLOCK, key)) {
if (Inventory_CheckChangeSelected() && Inventory_SelectedBlock != BLOCK_AIR) {
/* Don't assign SelectedIndex directly, because we don't want held block
switching positions if they already have air in their inventory hotbar. */
Inventory_Set(Inventory.SelectedIndex, BLOCK_AIR);
Event_RaiseVoid(&UserEvents.HeldBlockChanged);
}
} else if (key == KeyBinds[KEYBIND_IDOVERLAY]) {
} else if (KeyBind_Claims(KEYBIND_IDOVERLAY, key)) {
TexIdsOverlay_Show();
} else if (key == KeyBinds[KEYBIND_BREAK_LIQUIDS]) {
} else if (KeyBind_Claims(KEYBIND_BREAK_LIQUIDS, key)) {
InputHandler_Toggle(key, &Game_BreakableLiquids,
" &eBreakable liquids is &aenabled",
" &eBreakable liquids is &cdisabled");
@ -956,11 +953,11 @@ static cc_bool HandleNonClassicKey(int key) {
}
static cc_bool HandleCoreKey(int key) {
if (key == KeyBinds[KEYBIND_HIDE_FPS]) {
if (KeyBind_Claims(KEYBIND_HIDE_FPS, key)) {
Gui.ShowFPS = !Gui.ShowFPS;
} else if (key == KeyBinds[KEYBIND_FULLSCREEN]) {
} else if (KeyBind_Claims(KEYBIND_FULLSCREEN, key)) {
Game_ToggleFullscreen();
} else if (key == KeyBinds[KEYBIND_FOG]) {
} else if (KeyBind_Claims(KEYBIND_FOG, key)) {
Game_CycleViewDistance();
} else if (key == CCKEY_F5 && Game_ClassicMode) {
int weather = Env.Weather == WEATHER_SUNNY ? WEATHER_RAINY : WEATHER_SUNNY;
@ -989,15 +986,15 @@ static void HandleHotkeyDown(int key) {
}
static cc_bool HandleLocalPlayerKey(int key) {
if (key == KeyBinds[KEYBIND_RESPAWN]) {
if (KeyBind_Claims(KEYBIND_RESPAWN, key)) {
return LocalPlayer_HandleRespawn();
} else if (key == KeyBinds[KEYBIND_SET_SPAWN]) {
} else if (KeyBind_Claims(KEYBIND_SET_SPAWN, key)) {
return LocalPlayer_HandleSetSpawn();
} else if (key == KeyBinds[KEYBIND_FLY]) {
} else if (KeyBind_Claims(KEYBIND_FLY, key)) {
return LocalPlayer_HandleFly();
} else if (key == KeyBinds[KEYBIND_NOCLIP]) {
} else if (KeyBind_Claims(KEYBIND_NOCLIP, key)) {
return LocalPlayer_HandleNoclip();
} else if (key == KeyBinds[KEYBIND_JUMP]) {
} else if (KeyBind_Claims(KEYBIND_JUMP, key)) {
return LocalPlayer_HandleJump();
}
return false;
@ -1091,7 +1088,7 @@ static void OnInputDown(void* obj, int key, cc_bool was) {
if (InputHandler_IsShutdown(key)) {
/* TODO: Do we need a separate exit function in Game class? */
Window_Close(); return;
} else if (key == KeyBinds[KEYBIND_SCREENSHOT] && !was) {
} else if (KeyBind_Claims(KEYBIND_SCREENSHOT, key) && !was) {
Game_ScreenshotRequested = true; return;
}
@ -1101,7 +1098,7 @@ static void OnInputDown(void* obj, int key, cc_bool was) {
if (s->VTABLE->HandlesInputDown(s, key)) return;
}
if ((Input_IsEscapeButton(key) || key == CCKEY_PAUSE) && !Gui.InputGrab) {
if (Input_IsPauseButton(key) && !Gui.InputGrab) {
#ifdef CC_BUILD_WEB
/* Can't do this in KeyUp, because pressing escape without having */
/* explicitly disabled mouse lock means a KeyUp event isn't sent. */
@ -1125,7 +1122,7 @@ static void OnInputUp(void* obj, int key) {
struct Screen* s;
int i;
if (key == KeyBinds[KEYBIND_ZOOM_SCROLL]) Camera_SetFov(Camera.DefaultFov);
if (KeyBind_Claims(KEYBIND_ZOOM_SCROLL, key)) Camera_SetFov(Camera.DefaultFov);
#ifdef CC_BUILD_WEB
/* When closing menus (which reacquires mouse focus) in key down, */
/* this still leaves the cursor visible. But if this is instead */
@ -1143,9 +1140,9 @@ static void OnInputUp(void* obj, int key) {
}
if (Gui.InputGrab) return;
if (key == KeyBinds[KEYBIND_DELETE_BLOCK]) MouseStateRelease(MOUSE_LEFT);
if (key == KeyBinds[KEYBIND_PLACE_BLOCK]) MouseStateRelease(MOUSE_RIGHT);
if (key == KeyBinds[KEYBIND_PICK_BLOCK]) MouseStateRelease(MOUSE_MIDDLE);
if (KeyBind_Claims(KEYBIND_DELETE_BLOCK, key)) MouseStateRelease(MOUSE_LEFT);
if (KeyBind_Claims(KEYBIND_PLACE_BLOCK, key)) MouseStateRelease(MOUSE_RIGHT);
if (KeyBind_Claims(KEYBIND_PICK_BLOCK, key)) MouseStateRelease(MOUSE_MIDDLE);
}
static void OnFocusChanged(void* obj) { if (!WindowInfo.Focused) Input_Clear(); }

View File

@ -90,7 +90,9 @@ void Input_Clear(void);
#define Input_IsDownButton(btn) ((btn) == CCKEY_DOWN || (btn) == CCPAD_DOWN)
#define Input_IsLeftButton(btn) ((btn) == CCKEY_LEFT || (btn) == CCPAD_LEFT)
#define Input_IsRightButton(btn) ((btn) == CCKEY_RIGHT || (btn) == CCPAD_RIGHT)
#define Input_IsEnterButton(btn) ((btn) == CCKEY_ENTER || (btn) == CCPAD_START || (btn) == CCKEY_KP_ENTER)
#define Input_IsPauseButton(btn) ((btn) == CCKEY_ESCAPE || (btn) == CCPAD_START || (btn) == CCKEY_PAUSE)
#define Input_IsEscapeButton(btn) ((btn) == CCKEY_ESCAPE || (btn) == CCPAD_SELECT)
#if defined CC_BUILD_HAIKU
@ -159,14 +161,18 @@ enum KeyBind_ {
};
typedef int KeyBind;
/* The keys that are bound to each key binding. */
extern cc_uint8 KeyBinds[KEYBIND_COUNT];
/* The keyboard/mouse buttons that are bound to each key binding */
extern cc_uint8 KeyBinds_Normal[KEYBIND_COUNT];
/* The gamepad buttons that are bound to each key binding */
extern cc_uint8 KeyBinds_Gamepad[KEYBIND_COUNT];
/* Default keyboard/mouse button that each key binding is bound to */
extern const cc_uint8 KeyBind_NormalDefaults[KEYBIND_COUNT];
/* Default gamepad button that each key binding is bound to */
extern const cc_uint8 KeyBind_GamepadDefaults[KEYBIND_COUNT];
#define KeyBind_GetDefaults() (Input.GamepadSource ? KeyBind_GamepadDefaults : KeyBind_NormalDefaults)
/* Whether the given keyboard/mouse or gamepad button is bound to the given keybinding */
#define KeyBind_Claims(binding, btn) (KeyBinds_Normal[binding] == (btn) || KeyBinds_Gamepad[binding] == (btn))
/* Gets whether the key bound to the given key binding is pressed. */
CC_API cc_bool KeyBind_IsPressed(KeyBind binding);
/* Set the key that the given key binding is bound to. (also updates options list) */

View File

@ -20,8 +20,8 @@
#include "Http.h"
#define LAYOUTS static const struct LLayout
#define IsEnterButton(btn) (Input_IsEnterButton(btn) || btn == CCPAD_A)
#define IsEscapeButton(btn) (Input_IsEscapeButton(btn) || btn == CCPAD_B)
#define IsEnterButton(btn) (btn == CCKEY_ENTER || btn == CCPAD_START || btn == CCPAD_A || btn == CCKEY_KP_ENTER)
#define IsBackButton(btn) (btn == CCKEY_ESCAPE || btn == CCPAD_SELECT || btn == CCPAD_B)
/*########################################################################################################################*
*---------------------------------------------------------Screen base-----------------------------------------------------*
@ -109,7 +109,7 @@ static void LScreen_KeyDown(struct LScreen* s, int key, cc_bool was) {
LScreen_CycleSelected(s, -1);
} else if (Input_IsDownButton(key)) {
LScreen_CycleSelected(s, 1);
} else if (IsEscapeButton(key) && s->onEscapeWidget) {
} else if (IsBackButton(key) && s->onEscapeWidget) {
s->onEscapeWidget->OnClick(s->onEscapeWidget);
}
}

View File

@ -3582,7 +3582,7 @@ static void TexIdsOverlay_Render(void* screen, double delta) {
static int TexIdsOverlay_KeyDown(void* screen, int key) {
struct Screen* s = (struct Screen*)screen;
if (key == KeyBinds[KEYBIND_IDOVERLAY]) { Gui_Remove(s); return true; }
if (KeyBind_Claims(KEYBIND_IDOVERLAY, key)) { Gui_Remove(s); return true; }
return false;
}

View File

@ -708,7 +708,7 @@ static int TabListOverlay_PointerDown(void* screen, int id, int x, int y) {
static void TabListOverlay_KeyUp(void* screen, int key) {
struct TabListOverlay* s = (struct TabListOverlay*)screen;
if (key != KeyBinds[KEYBIND_TABLIST] || s->staysOpen) return;
if (!KeyBind_Claims(KEYBIND_TABLIST, key) || s->staysOpen) return;
Gui_Remove((struct Screen*)s);
}
@ -1206,10 +1206,10 @@ static int ChatScreen_TextChanged(void* screen, const cc_string* str) {
static int ChatScreen_KeyDown(void* screen, int key) {
static const cc_string slash = String_FromConst("/");
struct ChatScreen* s = (struct ChatScreen*)screen;
int playerListKey = KeyBinds[KEYBIND_TABLIST];
cc_bool handlesList = playerListKey != CCKEY_TAB || !Gui.TabAutocomplete || !s->grabsInput;
int playerListKey = KeyBinds_Normal[KEYBIND_TABLIST];
cc_bool handlesList = playerListKey != CCKEY_TAB || !Gui.TabAutocomplete || !s->grabsInput;
if (key == playerListKey && handlesList) {
if (KeyBind_Claims(KEYBIND_TABLIST, key) && handlesList) {
if (!tablist_active && !Server.IsSinglePlayer) {
TabListOverlay_Show();
}
@ -1221,10 +1221,10 @@ static int ChatScreen_KeyDown(void* screen, int key) {
if (s->grabsInput) {
#ifdef CC_BUILD_WEB
/* See reason for this in HandleInputUp */
if (key == KeyBinds[KEYBIND_SEND_CHAT] || key == CCKEY_KP_ENTER) {
if (KeyBind_Claims(KEYBIND_SEND_CHAT, key) || key == CCKEY_KP_ENTER) {
ChatScreen_EnterChatInput(s, false);
#else
if (key == KeyBinds[KEYBIND_SEND_CHAT] || key == CCKEY_KP_ENTER || Input_IsEscapeButton(key)) {
if (KeyBind_Claims(KEYBIND_SEND_CHAT, key) || key == CCKEY_KP_ENTER || Input_IsEscapeButton(key)) {
ChatScreen_EnterChatInput(s, Input_IsEscapeButton(key));
#endif
} else if (key == CCKEY_PAGEUP) {
@ -1237,11 +1237,11 @@ static int ChatScreen_KeyDown(void* screen, int key) {
return key < CCKEY_F1 || key > CCKEY_F24;
}
if (key == KeyBinds[KEYBIND_CHAT]) {
if (KeyBind_Claims(KEYBIND_CHAT, key)) {
ChatScreen_OpenInput(&String_Empty);
} else if (key == CCKEY_SLASH) {
ChatScreen_OpenInput(&slash);
} else if (key == KeyBinds[KEYBIND_INVENTORY]) {
} else if (KeyBind_Claims(KEYBIND_INVENTORY, key)) {
InventoryScreen_Show();
} else {
return false;
@ -1263,7 +1263,7 @@ static void ChatScreen_KeyUp(void* screen, int key) {
if (key == CCKEY_ESCAPE) ChatScreen_EnterChatInput(s, true);
#endif
if (Server.SupportsFullCP437 && key == KeyBinds[KEYBIND_EXT_INPUT]) {
if (Server.SupportsFullCP437 && KeyBind_Claims(KEYBIND_EXT_INPUT, key)) {
if (!WindowInfo.Focused) return;
ChatScreen_ToggleAltInput(s);
}
@ -1592,7 +1592,7 @@ static int InventoryScreen_KeyDown(void* screen, int key) {
struct InventoryScreen* s = (struct InventoryScreen*)screen;
struct TableWidget* table = &s->table;
if (key == KeyBinds[KEYBIND_INVENTORY] && s->releasedInv) {
if (KeyBind_Claims(KEYBIND_INVENTORY, key) && s->releasedInv) {
Gui_Remove((struct Screen*)s);
} else if (Input_IsEnterButton(key) && table->selectedIndex != -1) {
Inventory_SetSelectedBlock(table->blocks[table->selectedIndex]);
@ -1612,7 +1612,7 @@ static cc_bool InventoryScreen_IsHotbarActive(void) {
static void InventoryScreen_KeyUp(void* screen, int key) {
struct InventoryScreen* s = (struct InventoryScreen*)screen;
if (key == KeyBinds[KEYBIND_INVENTORY]) s->releasedInv = true;
if (KeyBind_Claims(KEYBIND_INVENTORY, key)) s->releasedInv = true;
}
static int InventoryScreen_PointerDown(void* screen, int id, int x, int y) {
@ -2151,7 +2151,7 @@ static void TouchScreen_HalfClick(void* s, void* w) {
static void TouchScreen_BindClick(void* screen, void* widget) {
struct TouchScreen* s = (struct TouchScreen*)screen;
int i = Screen_Index(screen, widget) - ONSCREEN_MAX_BTNS;
Input_Set(KeyBinds[s->descs[i].bind], true);
Input_Set(KeyBinds_Normal[s->descs[i].bind], true);
}
static const struct TouchButtonDesc onscreenDescs[ONSCREEN_MAX_BTNS] = {
@ -2283,7 +2283,7 @@ static void TouchScreen_PointerUp(void* screen, int id, int x, int y) {
if (!(s->btns[i].active & id)) continue;
if (s->descs[i].bind < KEYBIND_COUNT) {
Input_Set(KeyBinds[s->descs[i].bind], false);
Input_Set(KeyBinds_Normal[s->descs[i].bind], false);
}
s->btns[i].active &= ~id;
return;

View File

@ -512,7 +512,7 @@ static int HotbarWidget_MapKey(int key) {
int i;
for (i = 0; i < INVENTORY_BLOCKS_PER_HOTBAR; i++)
{
if (key == KeyBinds[KEYBIND_HOTBAR_1 + i]) return i;
if (KeyBind_Claims(KEYBIND_HOTBAR_1 + i, key)) return i;
}
return -1;
}
@ -532,9 +532,9 @@ static int HotbarWidget_KeyDown(void* widget, int key) {
int index = HotbarWidget_MapKey(key);
if (index == -1) {
if (key == KeyBinds[KEYBIND_HOTBAR_LEFT])
if (KeyBind_Claims(KEYBIND_HOTBAR_LEFT, key))
return HotbarWidget_CycleIndex(-1);
if (key == KeyBinds[KEYBIND_HOTBAR_RIGHT])
if (KeyBind_Claims(KEYBIND_HOTBAR_RIGHT, key))
return HotbarWidget_CycleIndex(+1);
return false;
}
@ -555,7 +555,7 @@ static void HotbarWidget_InputUp(void* widget, int key) {
a) user presses alt then number
b) user presses alt
We only do case b) if case a) did not happen */
if (key != KeyBinds[KEYBIND_HOTBAR_SWITCH]) return;
if (!KeyBind_Claims(KEYBIND_HOTBAR_SWITCH, key)) return;
if (w->altHandled) { w->altHandled = false; return; } /* handled already */
/* Don't switch hotbar when alt+tabbing to another window */

View File

@ -259,14 +259,14 @@ static void ProcessNunchuck_Game(int mods, double delta) {
Input_SetNonRepeatable(CCPAD_START, mods & WPAD_BUTTON_HOME);
Input_SetNonRepeatable(CCPAD_SELECT, mods & WPAD_BUTTON_MINUS);
Input_SetNonRepeatable(KeyBinds[KEYBIND_FLY], mods & WPAD_BUTTON_LEFT);
Input_SetNonRepeatable(KeyBinds_Normal[KEYBIND_FLY], mods & WPAD_BUTTON_LEFT);
if (mods & WPAD_BUTTON_RIGHT) {
Mouse_ScrollWheel(1.0*delta);
}
Input_SetNonRepeatable(KeyBinds[KEYBIND_THIRD_PERSON], mods & WPAD_BUTTON_UP);
Input_SetNonRepeatable(KeyBinds[KEYBIND_FLY_DOWN], mods & WPAD_BUTTON_DOWN);
Input_SetNonRepeatable(KeyBinds_Normal[KEYBIND_THIRD_PERSON], mods & WPAD_BUTTON_UP);
Input_SetNonRepeatable(KeyBinds_Normal[KEYBIND_FLY_DOWN], mods & WPAD_BUTTON_DOWN);
const float ANGLE_DELTA = 50;
bool nunchuckUp = (analog.ang > -ANGLE_DELTA) && (analog.ang < ANGLE_DELTA) && (analog.mag > 0.5);