diff --git a/.github/workflows/build_3ds.yml b/.github/workflows/build_3ds.yml index 4b7b2f37f..0cf704a73 100644 --- a/.github/workflows/build_3ds.yml +++ b/.github/workflows/build_3ds.yml @@ -7,6 +7,7 @@ concurrency: jobs: build-3DS: + if: github.ref_name == github.event.repository.default_branch runs-on: ubuntu-latest container: image: devkitpro/devkitarm:latest diff --git a/.github/workflows/build_haiku.yml b/.github/workflows/build_haiku.yml index 336f2040e..c5aa81421 100644 --- a/.github/workflows/build_haiku.yml +++ b/.github/workflows/build_haiku.yml @@ -7,6 +7,7 @@ concurrency: jobs: build-haiku: + if: github.ref_name == github.event.repository.default_branch runs-on: ubuntu-latest container: image: haiku/cross-compiler:x86_64-r1beta4 diff --git a/.github/workflows/build_psp.yml b/.github/workflows/build_psp.yml index fc325a001..ddadbc569 100644 --- a/.github/workflows/build_psp.yml +++ b/.github/workflows/build_psp.yml @@ -7,6 +7,7 @@ concurrency: jobs: build-PSP: + if: github.ref_name == github.event.repository.default_branch runs-on: ubuntu-latest container: image: pspdev/pspdev:latest diff --git a/.github/workflows/build_wiigc.yml b/.github/workflows/build_wiigc.yml index 3c021c672..d311e2b1b 100644 --- a/.github/workflows/build_wiigc.yml +++ b/.github/workflows/build_wiigc.yml @@ -7,6 +7,7 @@ concurrency: jobs: build: + if: github.ref_name == github.event.repository.default_branch runs-on: ubuntu-latest container: image: devkitpro/devkitppc:latest diff --git a/src/Input.c b/src/Input.c index 990e105c1..1a66e5e49 100644 --- a/src/Input.c +++ b/src/Input.c @@ -393,15 +393,16 @@ static void KeyBind_Load(const char* prefix, cc_uint8* keybinds, const cc_uint8* } } -void KeyBind_Set(KeyBind binding, int key) { +void KeyBind_Set(KeyBind binding, int key, cc_uint8* binds) { cc_string name; char nameBuffer[STRING_SIZE]; cc_string value; String_InitArray(name, nameBuffer); - String_Format1(&name, "key-%c", keybindNames[binding]); + String_Format1(&name, binds == KeyBinds_Gamepad ? "pad-%c" : "key-%c", + keybindNames[binding]); value = String_FromReadonly(storageNames[key]); Options_SetString(&name, &value); - KeyBinds[binding] = key; + binds[binding] = key; } /* Initialises and loads key bindings from options */ diff --git a/src/Input.h b/src/Input.h index cc4b9c59a..8fc789b07 100644 --- a/src/Input.h +++ b/src/Input.h @@ -62,14 +62,17 @@ extern struct _InputState { cc_bool Pressed[INPUT_COUNT]; /* Whether raw mouse/touch input is currently being listened for */ cc_bool RawMode; - /* Whether a gamepad is available as an input source */ - cc_bool GamepadSource; + /* Sources available for input (Mouse/Keyboard, Gamepad) */ + cc_uint8 Sources; /* Whether a gamepad joystick is being used to control player movement */ cc_bool JoystickMovement; /* Angle of the gamepad joystick being used to control player movement */ float JoystickAngle; } Input; +#define INPUT_SOURCE_NORMAL (1 << 0) +#define INPUT_SOURCE_GAMEPAD (1 << 1) + /* Sets Input_Pressed[key] to true and raises InputEvents.Down */ void Input_SetPressed(int key); /* Sets Input_Pressed[key] to false and raises InputEvents.Up */ @@ -176,7 +179,7 @@ extern const cc_uint8 KeyBind_GamepadDefaults[KEYBIND_COUNT]; /* 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) */ -void KeyBind_Set(KeyBind binding, int key); +void KeyBind_Set(KeyBind binding, int key, cc_uint8* binds); /* whether to leave text input open for user to enter further input */ #define HOTKEY_FLAG_STAYS_OPEN 0x01 diff --git a/src/Menus.c b/src/Menus.c index affcfce3e..e65453657 100644 --- a/src/Menus.c +++ b/src/Menus.c @@ -209,6 +209,7 @@ static void Menu_SwitchBindsHacks(void* a, void* b) { HacksBindingsScreen static void Menu_SwitchBindsOther(void* a, void* b) { OtherBindingsScreen_Show(); } static void Menu_SwitchBindsMouse(void* a, void* b) { MouseBindingsScreen_Show(); } static void Menu_SwitchBindsHotbar(void* a, void* b) { HotbarBindingsScreen_Show(); } +static void SwitchBindsMain(void* s, void* w); static void Menu_SwitchMisc(void* a, void* b) { MiscOptionsScreen_Show(); } static void Menu_SwitchChat(void* a, void* b) { ChatOptionsScreen_Show(); } @@ -696,7 +697,7 @@ static const struct SimpleButtonDesc optsGroup_btns[8] = { { -160, -100, "Misc options...", Menu_SwitchMisc }, { -160, -50, "Gui options...", Menu_SwitchGui }, { -160, 0, "Graphics options...", Menu_SwitchGfx }, - { -160, 50, "Controls...", Menu_SwitchBindsNormal }, + { -160, 50, "Controls...", SwitchBindsMain }, { 160, -100, "Chat options...", Menu_SwitchChat }, { 160, -50, "Hacks settings...", Menu_SwitchHacks }, { 160, 0, "Env settings...", Menu_SwitchEnv }, @@ -1812,6 +1813,91 @@ void LoadLevelScreen_Show(void) { } + +/*########################################################################################################################* +*----------------------------------------------------EditHotkeyScreen-----------------------------------------------------* +*#########################################################################################################################*/ +static struct BindsSourceScreen { + Screen_Body + struct ButtonWidget btns[2], cancel; +} BindsSourceScreen; +static int binds_gamepad; /* Default to Normal (Keyboard/Mouse) */ + +static struct Widget* bindsSource_widgets[] = { + (struct Widget*)&BindsSourceScreen.btns[0], (struct Widget*)&BindsSourceScreen.btns[1], + (struct Widget*)&BindsSourceScreen.cancel +}; +#define BINDSSOURCE_MAX_VERTICES (BUTTONWIDGET_MAX * 3) + +static void BindsSourceScreen_ModeNormal(void* screen, void* b) { + binds_gamepad = false; + NormalBindingsScreen_Show(); +} + +static void BindsSourceScreen_ModeGamepad(void* screen, void* b) { + binds_gamepad = true; + NormalBindingsScreen_Show(); +} + +static void BindsSourceScreen_ContextRecreated(void* screen) { + struct BindsSourceScreen* s = (struct BindsSourceScreen*)screen; + struct FontDesc font; + + ButtonWidget_SetConst(&s->btns[0], "Keyboard/Mouse", &font); + ButtonWidget_SetConst(&s->btns[1], "Gamepad/Controller", &font); + ButtonWidget_SetConst(&s->cancel, "Cancel", &font); + Font_Free(&font); +} + +static void BindsSourceScreen_Layout(void* screen) { + struct BindsSourceScreen* s = (struct BindsSourceScreen*)screen; + Widget_SetLocation(&s->btns[0], ANCHOR_CENTRE, ANCHOR_CENTRE, 0, -50); + Widget_SetLocation(&s->btns[1], ANCHOR_CENTRE, ANCHOR_CENTRE, 0, 50); + Menu_LayoutBack(&s->cancel); +} + +static void BindsSourceScreen_Init(void* screen) { + struct BindsSourceScreen* s = (struct BindsSourceScreen*)screen; + + s->widgets = bindsSource_widgets; + s->numWidgets = Array_Elems(bindsSource_widgets); + s->selectedI = -1; + s->maxVertices = BINDSSOURCE_MAX_VERTICES; + + ButtonWidget_Init(&s->btns[0], 300, BindsSourceScreen_ModeNormal); + ButtonWidget_Init(&s->btns[1], 300, BindsSourceScreen_ModeGamepad); + ButtonWidget_Init(&s->cancel, 400, Menu_SwitchHotkeys); +} + +static const struct ScreenVTABLE BindsSourceScreen_VTABLE = { + BindsSourceScreen_Init, Screen_NullUpdate, Screen_NullFunc, + MenuScreen_Render2, Screen_BuildMesh, + Menu_InputDown, Screen_InputUp, Screen_TKeyPress, Screen_TText, + Menu_PointerDown, Screen_PointerUp, Menu_PointerMove, Screen_TMouseScroll, + BindsSourceScreen_Layout, Screen_ContextLost, BindsSourceScreen_ContextRecreated +}; +void BindsSourceScreen_Show(void) { + struct BindsSourceScreen* s = &BindsSourceScreen; + s->grabsInput = true; + s->closable = true; + s->VTABLE = &BindsSourceScreen_VTABLE; + Gui_Add((struct Screen*)s, GUI_PRIORITY_MENU); +} + +static void SwitchBindsMain(void* s, void* w) { + if (Input.Sources & (INPUT_SOURCE_NORMAL | INPUT_SOURCE_GAMEPAD)) { + /* User needs to decide whether to configure mouse/keyboard or gamepad */ + BindsSourceScreen_Show(); + } else if (Input.Sources & INPUT_SOURCE_GAMEPAD) { + binds_gamepad = true; + NormalBindingsScreen_Show(); + } else { + binds_gamepad = false; + NormalBindingsScreen_Show(); + } +} + + /*########################################################################################################################* *---------------------------------------------------KeyBindsScreen-----------------------------------------------------* *#########################################################################################################################*/ @@ -1844,10 +1930,13 @@ static struct Widget* key_widgets[KEYBINDS_MAX_BTNS + 5] = { static void KeyBindsScreen_Update(struct KeyBindsScreen* s, int i) { cc_string text; char textBuffer[STRING_SIZE]; + const cc_uint8* curBinds; + String_InitArray(text, textBuffer); + curBinds = binds_gamepad ? KeyBinds_Gamepad : KeyBinds_Normal; String_Format2(&text, s->curI == i ? "> %c: %c <" : "%c: %c", - s->descs[i], Input_DisplayNames[KeyBinds[s->binds[i]]]); + s->descs[i], Input_DisplayNames[curBinds[s->binds[i]]]); ButtonWidget_Set(&s->buttons[i], &text, &s->titleFont); s->dirty = true; } @@ -1866,15 +1955,17 @@ static void KeyBindsScreen_OnBindingClick(void* screen, void* widget) { static int KeyBindsScreen_KeyDown(void* screen, int key) { struct KeyBindsScreen* s = (struct KeyBindsScreen*)screen; const cc_uint8* defaults; + cc_uint8* curBinds; KeyBind bind; int idx; if (s->curI == -1) return Menu_InputDown(s, key); - defaults = KeyBind_GetDefaults(); + curBinds = binds_gamepad ? KeyBinds_Gamepad : KeyBinds_Normal; + defaults = binds_gamepad ? KeyBind_GamepadDefaults : KeyBind_NormalDefaults; bind = s->binds[s->curI]; if (Input_IsEscapeButton(key)) key = defaults[bind]; - KeyBind_Set(bind, key); + KeyBind_Set(bind, key, curBinds); idx = s->curI; s->curI = -1; @@ -2000,7 +2091,8 @@ static void KeyBindsScreen_Show(int bindsCount, const cc_uint8* binds, const cha void ClassicBindingsScreen_Show(void) { static const cc_uint8 binds[] = { KEYBIND_FORWARD, KEYBIND_BACK, KEYBIND_JUMP, KEYBIND_CHAT, KEYBIND_SET_SPAWN, KEYBIND_LEFT, KEYBIND_RIGHT, KEYBIND_INVENTORY, KEYBIND_FOG, KEYBIND_RESPAWN }; static const char* const descs[] = { "Forward", "Back", "Jump", "Chat", "Save location", "Left", "Right", "Build", "Toggle fog", "Load location" }; - + binds_gamepad = false; + if (Game_ClassicHacks) { KeyBindsScreen_Reset(NULL, Menu_SwitchBindsClassicHacks, 260); } else { @@ -2018,6 +2110,7 @@ void ClassicBindingsScreen_Show(void) { void ClassicHacksBindingsScreen_Show(void) { static const cc_uint8 binds[6] = { KEYBIND_SPEED, KEYBIND_NOCLIP, KEYBIND_HALF_SPEED, KEYBIND_FLY, KEYBIND_FLY_UP, KEYBIND_FLY_DOWN }; static const char* const descs[6] = { "Speed", "Noclip", "Half speed", "Fly", "Fly up", "Fly down" }; + binds_gamepad = false; KeyBindsScreen_Reset(Menu_SwitchBindsClassic, NULL, 260); KeyBindsScreen_SetLayout(-90, -40, 3); diff --git a/src/Window_3DS.c b/src/Window_3DS.c index 66f382db6..9be979e10 100644 --- a/src/Window_3DS.c +++ b/src/Window_3DS.c @@ -50,8 +50,8 @@ void Window_Init(void) { WindowInfo.Focused = true; WindowInfo.Exists = true; - Input.GamepadSource = true; - irrst_result = irrstInit(); + Input.Sources = INPUT_SOURCE_GAMEPAD; + irrst_result = irrstInit(); } void Window_Create2D(int width, int height) { launcherMode = true; } diff --git a/src/Window_Dreamcast.c b/src/Window_Dreamcast.c index 61fbd5f2b..35ad02573 100644 --- a/src/Window_Dreamcast.c +++ b/src/Window_Dreamcast.c @@ -31,7 +31,7 @@ void Window_Init(void) { WindowInfo.Focused = true; WindowInfo.Exists = true; - Input.GamepadSource = true; + Input.Sources = INPUT_SOURCE_GAMEPAD; } void Window_Create2D(int width, int height) { diff --git a/src/Window_GCWii.c b/src/Window_GCWii.c index 7ec0163a3..03de52098 100644 --- a/src/Window_GCWii.c +++ b/src/Window_GCWii.c @@ -72,7 +72,7 @@ void Window_Init(void) { WindowInfo.Focused = true; WindowInfo.Exists = true; - Input.GamepadSource = true; + Input.Sources = INPUT_SOURCE_GAMEPAD; #if defined HW_RVL WPAD_Init(); WPAD_SetDataFormat(0, WPAD_FMT_BTNS_ACC_IR); diff --git a/src/Window_PSP.c b/src/Window_PSP.c index 3c463f49f..cad37b32e 100644 --- a/src/Window_PSP.c +++ b/src/Window_PSP.c @@ -37,7 +37,7 @@ void Window_Init(void) { WindowInfo.Focused = true; WindowInfo.Exists = true; - Input.GamepadSource = true; + Input.Sources = INPUT_SOURCE_GAMEPAD; sceCtrlSetSamplingCycle(0); sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG); } diff --git a/src/Window_PSVita.c b/src/Window_PSVita.c index 33fd234fe..b5e10b82b 100644 --- a/src/Window_PSVita.c +++ b/src/Window_PSVita.c @@ -37,7 +37,7 @@ void Window_Init(void) { WindowInfo.Focused = true; WindowInfo.Exists = true; - Input.GamepadSource = true; + Input.Sources = INPUT_SOURCE_GAMEPAD; sceCtrlSetSamplingMode(SCE_CTRL_MODE_ANALOG); sceTouchSetSamplingState(SCE_TOUCH_PORT_FRONT, SCE_TOUCH_SAMPLING_STATE_START); sceTouchSetSamplingState(SCE_TOUCH_PORT_BACK, SCE_TOUCH_SAMPLING_STATE_START); diff --git a/src/Window_Xbox.c b/src/Window_Xbox.c index 185033d07..700c5cd53 100644 --- a/src/Window_Xbox.c +++ b/src/Window_Xbox.c @@ -75,7 +75,7 @@ void Window_Init(void) { WindowInfo.Focused = true; WindowInfo.Exists = true; - Input.GamepadSource = true; + Input.Sources = INPUT_SOURCE_GAMEPAD; usbh_core_init(); usbh_xid_init();