Touch UI: Allow left-aligning on-screen buttons

This commit is contained in:
UnknownShadow200 2024-04-28 19:27:41 +10:00
parent da3a0f6154
commit b61562a5c7
2 changed files with 113 additions and 75 deletions

View File

@ -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"

View File

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