From b61562a5c76c572f1bba1a1936b5a4652033a5b8 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 28 Apr 2024 19:27:41 +1000 Subject: [PATCH] Touch UI: Allow left-aligning on-screen buttons --- src/Options.h | 1 + src/TouchUI.c | 187 ++++++++++++++++++++++++++++++-------------------- 2 files changed, 113 insertions(+), 75 deletions(-) diff --git a/src/Options.h b/src/Options.h index 4620f6423..711055676 100644 --- a/src/Options.h +++ b/src/Options.h @@ -72,6 +72,7 @@ Copyright 2014-2023 ClassiCube | Licensed under BSD-3 #define OPT_CAMERA_SMOOTH "camera-smooth" #define OPT_GRAB_CURSOR "win-grab-cursor" #define OPT_TOUCH_BUTTONS "gui-touchbuttons" +#define OPT_TOUCH_HALIGN "gui-touch-halign" #define OPT_TOUCH_SCALE "gui-touchscale" #define OPT_HTTP_ONLY "http-no-https" #define OPT_HTTPS_VERIFY "https-verify" diff --git a/src/TouchUI.c b/src/TouchUI.c index 4496cd145..408a6195e 100644 --- a/src/TouchUI.c +++ b/src/TouchUI.c @@ -49,36 +49,62 @@ static int GetOnscreenButtons(void) { Server.IsSinglePlayer ? DEFAULT_SP_ONSCREEN : DEFAULT_MP_ONSCREEN); } +static int GetOnscreenHAligns(void) { + return Options_GetInt(OPT_TOUCH_HALIGN, 0, Int32_MaxValue, 0); +} + /*########################################################################################################################* *---------------------------------------------------TouchControlsScreen---------------------------------------------------* *#########################################################################################################################*/ -#define ONSCREEN_PAGE_BTNS 8 +#define ONSCREEN_PAGE_BTNS 4 +#define ONSCREEN_NUM_PAGES 4 static struct TouchOnscreenScreen { Screen_Body struct ButtonWidget back, left, right; struct ButtonWidget btns[ONSCREEN_PAGE_BTNS]; - const struct SimpleButtonDesc* btnDescs; struct FontDesc font; + int page; } TouchOnscreenScreen; -static struct Widget* touchOnscreen_widgets[3 + ONSCREEN_PAGE_BTNS] = { - (struct Widget*)&TouchOnscreenScreen.back, (struct Widget*)&TouchOnscreenScreen.left, - (struct Widget*)&TouchOnscreenScreen.right, (struct Widget*)&TouchOnscreenScreen.btns[0], - (struct Widget*)&TouchOnscreenScreen.btns[1], (struct Widget*)&TouchOnscreenScreen.btns[2], - (struct Widget*)&TouchOnscreenScreen.btns[3], (struct Widget*)&TouchOnscreenScreen.btns[4], - (struct Widget*)&TouchOnscreenScreen.btns[5], (struct Widget*)&TouchOnscreenScreen.btns[6], - (struct Widget*)&TouchOnscreenScreen.btns[7] +static struct Widget* touchOnscreen_widgets[3 + ONSCREEN_PAGE_BTNS]; + +static const char* const touchOnscreen[ONSCREEN_PAGE_BTNS * ONSCREEN_NUM_PAGES] = { + "Chat", "Tablist", "Spawn", "Set spawn", + "Fly", "Noclip", "Speed", "Half speed", + "Third person", "Delete", "Pick", "Place", + "Switch hotbar", "---", "---", "---", }; -static void TouchOnscreen_UpdateColors(struct TouchOnscreenScreen* s) { +static void TouchOnscreen_UpdateButton(struct TouchOnscreenScreen* s, struct ButtonWidget* btn) { PackedCol grey = PackedCol_Make(0x7F, 0x7F, 0x7F, 0xFF); int buttons = GetOnscreenButtons(); - int i, bit; + int haligns = GetOnscreenHAligns(); + const char* label; + char buffer[64]; + cc_string str; + int bit; + bit = 1 << btn->meta.val; + btn->color = (buttons & bit) ? PACKEDCOL_WHITE : grey; + + String_InitArray(str, buffer); + label = touchOnscreen[btn->meta.val]; + + if ((buttons & bit) && (haligns & bit)) { + String_Format1(&str, "%c: Left aligned", label); + } else if (buttons & bit) { + String_Format1(&str, "%c: Right aligned", label); + } else { + String_AppendConst(&str, label); + } + ButtonWidget_Set(btn, &str, &s->font); +} + +static void TouchOnscreen_UpdateAll(struct TouchOnscreenScreen* s) { + int i; for (i = 0; i < ONSCREEN_PAGE_BTNS; i++) { - bit = s->btns[i].meta.val; - s->btns[i].color = (buttons & bit) ? PACKEDCOL_WHITE : grey; + TouchOnscreen_UpdateButton(s, &s->btns[i]); } } @@ -86,84 +112,68 @@ static void TouchOnscreen_Any(void* screen, void* w) { struct TouchOnscreenScreen* s = (struct TouchOnscreenScreen*)screen; struct ButtonWidget* btn = (struct ButtonWidget*)w; int buttons = GetOnscreenButtons(); - int bit = btn->meta.val; + int haligns = GetOnscreenHAligns(); + int bit = 1 << btn->meta.val; - if (buttons & bit) { + if ((buttons & bit) & (haligns & bit)) { buttons &= ~bit; + haligns &= ~bit; + } else if (buttons & bit) { + haligns |= bit; } else { buttons |= bit; } Options_SetInt(OPT_TOUCH_BUTTONS, buttons); - TouchOnscreen_UpdateColors(s); + Options_SetInt(OPT_TOUCH_HALIGN, haligns); + TouchOnscreen_UpdateButton(s, btn); TouchScreen_Refresh(); } static void TouchOnscreen_More(void* s, void* w) { TouchCtrlsScreen_Show(); } -static const struct SimpleButtonDesc touchOnscreen_page1[ONSCREEN_PAGE_BTNS] = { - { -120, -50, "Chat", TouchOnscreen_Any }, { 120, -50, "Tablist", TouchOnscreen_Any }, - { -120, 0, "Spawn", TouchOnscreen_Any }, { 120, 0, "Set spawn", TouchOnscreen_Any }, - { -120, 50, "Fly", TouchOnscreen_Any }, { 120, 50, "Noclip", TouchOnscreen_Any }, - { -120, 100, "Speed", TouchOnscreen_Any }, { 120, 100, "Half speed", TouchOnscreen_Any } -}; -static const struct SimpleButtonDesc touchOnscreen_page2[ONSCREEN_PAGE_BTNS] = { - { -120, -50, "Third person", TouchOnscreen_Any }, { 120, -50, "Delete", TouchOnscreen_Any }, - { -120, 0, "Pick", TouchOnscreen_Any }, { 120, 0, "Place", TouchOnscreen_Any }, - { -120, 50, "Switch hotbar", TouchOnscreen_Any }, { 120, 50, "---", TouchOnscreen_Any }, - { -120, 100, "---", TouchOnscreen_Any }, { 120, 100, "---", TouchOnscreen_Any } -}; - static void TouchOnscreen_Left(void* screen, void* b); static void TouchOnscreen_Right(void* screen, void* b); -static void TouchOnscreen_RemakeWidgets(struct TouchOnscreenScreen* s, cc_bool page1) { +static void TouchOnscreen_RemakeWidgets(struct TouchOnscreenScreen* s) { int i; - int offset = page1 ? 0 : ONSCREEN_PAGE_BTNS; - s->btnDescs = page1 ? touchOnscreen_page1 : touchOnscreen_page2; - + int offset = s->page * ONSCREEN_PAGE_BTNS; s->widgets = touchOnscreen_widgets; s->numWidgets = 0; s->maxWidgets = Array_Elems(touchOnscreen_widgets); - Menu_AddButtons(s, s->btns, 200, s->btnDescs, ONSCREEN_PAGE_BTNS); + for (i = 0; i < ONSCREEN_PAGE_BTNS; i++) + { + ButtonWidget_Add(s, &s->btns[i], 300, TouchOnscreen_Any); + s->btns[i].meta.val = i + offset; + } ButtonWidget_Add(s, &s->back, 400, TouchOnscreen_More); ButtonWidget_Add(s, &s->left, 40, TouchOnscreen_Left); ButtonWidget_Add(s, &s->right, 40, TouchOnscreen_Right); - Widget_SetDisabled(&s->left, page1); - Widget_SetDisabled(&s->right, !page1); - - for (i = 0; i < ONSCREEN_PAGE_BTNS; i++) - { - s->btns[i].meta.val = 1 << (i + offset); - } + Widget_SetDisabled(&s->left, s->page == 0); + Widget_SetDisabled(&s->right, s->page == ONSCREEN_NUM_PAGES - 1); } static void TouchOnscreen_Left(void* screen, void* b) { struct TouchOnscreenScreen* s = (struct TouchOnscreenScreen*)screen; - TouchOnscreen_RemakeWidgets(s, true); + s->page--; + TouchOnscreen_RemakeWidgets(s); Gui_Refresh((struct Screen*)s); - TouchOnscreen_UpdateColors(s); + TouchOnscreen_UpdateAll(s); } static void TouchOnscreen_Right(void* screen, void* b) { struct TouchOnscreenScreen* s = (struct TouchOnscreenScreen*)screen; - TouchOnscreen_RemakeWidgets(s, false); + s->page++; + TouchOnscreen_RemakeWidgets(s); Gui_Refresh((struct Screen*)s); - TouchOnscreen_UpdateColors(s); -} - -static void TouchOnscreenScreen_ContextLost(void* screen) { - struct TouchOnscreenScreen* s = (struct TouchOnscreenScreen*)screen; - Font_Free(&s->font); - Screen_ContextLost(screen); + TouchOnscreen_UpdateAll(s); } static void TouchOnscreenScreen_ContextRecreated(void* screen) { struct TouchOnscreenScreen* s = (struct TouchOnscreenScreen*)screen; - Gui_MakeTitleFont(&s->font); Screen_UpdateVb(screen); - Menu_SetButtons(s->btns, &s->font, s->btnDescs, ONSCREEN_PAGE_BTNS); + TouchOnscreen_UpdateAll(s); ButtonWidget_SetConst(&s->back, "Done", &s->font); ButtonWidget_SetConst(&s->left, "<", &s->font); ButtonWidget_SetConst(&s->right, ">", &s->font); @@ -171,26 +181,38 @@ static void TouchOnscreenScreen_ContextRecreated(void* screen) { static void TouchOnscreenScreen_Layout(void* screen) { struct TouchOnscreenScreen* s = (struct TouchOnscreenScreen*)screen; - Menu_LayoutButtons(s->btns, s->btnDescs, ONSCREEN_PAGE_BTNS); + int i; + for (i = 0; i < ONSCREEN_PAGE_BTNS; i++) + { + Widget_SetLocation(&s->btns[i], ANCHOR_CENTRE, ANCHOR_CENTRE, 0, -75 + i * 50); + } + Menu_LayoutBack(&s->back); - Widget_SetLocation(&s->left, ANCHOR_CENTRE, ANCHOR_CENTRE, -260, 0); - Widget_SetLocation(&s->right, ANCHOR_CENTRE, ANCHOR_CENTRE, 260, 0); + Widget_SetLocation(&s->left, ANCHOR_CENTRE, ANCHOR_CENTRE, -220, 0); + Widget_SetLocation(&s->right, ANCHOR_CENTRE, ANCHOR_CENTRE, 220, 0); } static void TouchOnscreenScreen_Init(void* screen) { struct TouchOnscreenScreen* s = (struct TouchOnscreenScreen*)screen; - TouchOnscreen_RemakeWidgets(s, true); - TouchOnscreen_UpdateColors(screen); + s->page = 0; + Gui_MakeTitleFont(&s->font); + TouchOnscreen_RemakeWidgets(s); + TouchOnscreen_UpdateAll(screen); s->maxVertices = Screen_CalcDefaultMaxVertices(s); } +static void TouchOnscreenScreen_Free(void* screen) { + struct TouchOnscreenScreen* s = (struct TouchOnscreenScreen*)screen; + Font_Free(&s->font); +} + static const struct ScreenVTABLE TouchOnscreenScreen_VTABLE = { - TouchOnscreenScreen_Init, Screen_NullUpdate, Screen_NullFunc, + TouchOnscreenScreen_Init, Screen_NullUpdate, TouchOnscreenScreen_Free, MenuScreen_Render2, Screen_BuildMesh, Menu_InputDown, Screen_InputUp, Screen_TKeyPress, Screen_TText, Menu_PointerDown, Screen_PointerUp, Menu_PointerMove, Screen_TMouseScroll, - TouchOnscreenScreen_Layout, TouchOnscreenScreen_ContextLost, TouchOnscreenScreen_ContextRecreated + TouchOnscreenScreen_Layout, Screen_ContextLost, TouchOnscreenScreen_ContextRecreated }; void TouchOnscreenScreen_Show(void) { struct TouchOnscreenScreen* s = &TouchOnscreenScreen; @@ -486,7 +508,6 @@ static struct TouchScreen { int numOnscreen, numBtns; struct FontDesc font; struct ThumbstickWidget thumbstick; - const struct TouchButtonDesc* onscreenDescs[ONSCREEN_MAX_BTNS]; struct ButtonWidget onscreen[ONSCREEN_MAX_BTNS]; struct ButtonWidget btns[TOUCH_EXTRA_BTNS], more; } TouchScreen; @@ -558,7 +579,7 @@ static const struct TouchButtonDesc hackDescs[2] = { { "\x1F", KEYBIND_FLY_DOWN, 50, 10, TouchScreen_BindClick } }; -#define TOUCHSCREEN_BTN_COLOR PackedCol_Make(255, 255, 255, 220) +#define TOUCHSCREEN_BTN_COLOR PackedCol_Make(255, 255, 255, 200) static void TouchScreen_InitButtons(struct TouchScreen* s) { struct HacksComp* hacks = &Entities.CurPlayer->Hacks; const struct TouchButtonDesc* desc; @@ -574,8 +595,9 @@ static void TouchScreen_InitButtons(struct TouchScreen* s) { ButtonWidget_Init(&s->onscreen[j], 100, desc->OnClick); if (desc->enabled) Widget_SetDisabled(&s->onscreen[j], !(*desc->enabled)); - s->onscreenDescs[j] = desc; - s->widgets[j] = (struct Widget*)&s->onscreen[j]; + s->onscreen[j].meta.val = i; + s->onscreen[j].color = TOUCHSCREEN_BTN_COLOR; + s->widgets[j] = (struct Widget*)&s->onscreen[j]; j++; } @@ -622,7 +644,7 @@ static void TouchScreen_ContextRecreated(void* screen) { for (i = 0; i < s->numOnscreen; i++) { - desc = s->onscreenDescs[i]; + desc = &onscreenDescs[s->onscreen[i].meta.val]; ButtonWidget_SetConst(&s->onscreen[i], desc->text, &s->font); } for (i = 0; i < s->numBtns; i++) @@ -679,10 +701,33 @@ static void TouchScreen_PointerUp(void* screen, int id, int x, int y) { } } +static void TouchScreen_LayoutOnscreen(struct TouchScreen* s, cc_uint8 alignment) { + int haligns = GetOnscreenHAligns(); + cc_uint8 halign; + int i, index, x, y; + + for (i = 0, x = 10, y = 10; i < s->numOnscreen; i++) + { + index = s->onscreen[i].meta.val; + halign = (haligns & (1 << index)) ? ANCHOR_MIN : ANCHOR_MAX; + if (halign != alignment) continue; + + Widget_SetLocation(&s->onscreen[i], halign, ANCHOR_MIN, x, y); + if (s->onscreen[i].y + s->onscreen[i].height <= s->btns[0].y){ y += 40; continue; } + + // overflowed onto jump/fly buttons, move to next column + y = 10; + x += 110; + Widget_SetLocation(&s->onscreen[i], halign, ANCHOR_MIN, x, y); + } +} + static void TouchScreen_Layout(void* screen) { struct TouchScreen* s = (struct TouchScreen*)screen; const struct TouchButtonDesc* desc; + int haligns = GetOnscreenHAligns(); float scale = Gui.RawTouchScale; + cc_uint8 halign; int i, x, y, height; /* Need to align these relative to the hotbar */ @@ -700,16 +745,8 @@ static void TouchScreen_Layout(void* screen) { Widget_Layout(&s->btns[i]); } - for (i = 0, x = 10, y = 10; i < s->numOnscreen; i++, y += 40) - { - Widget_SetLocation(&s->onscreen[i], ANCHOR_MAX, ANCHOR_MIN, x, y); - if (s->onscreen[i].y + s->onscreen[i].height <= s->btns[0].y) continue; - - // overflowed onto jump/fly buttons, move to next column - y = 10; - x += 110; - Widget_SetLocation(&s->onscreen[i], ANCHOR_MAX, ANCHOR_MIN, x, y); - } + TouchScreen_LayoutOnscreen(s, ANCHOR_MIN); + TouchScreen_LayoutOnscreen(s, ANCHOR_MAX); Widget_SetLocation(&s->more, ANCHOR_CENTRE, ANCHOR_MIN, 0, 10); Widget_SetLocation(&s->thumbstick, ANCHOR_MIN, ANCHOR_MAX, 30, 5);