mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-17 11:35:08 -04:00
Touch UI: Allow left-aligning on-screen buttons
This commit is contained in:
parent
da3a0f6154
commit
b61562a5c7
@ -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"
|
||||
|
187
src/TouchUI.c
187
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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user