mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-13 01:26:50 -04:00
Merge pull request #616 from UnknownShadow200/GUIRE4
Improvements to mobile GUI and input
This commit is contained in:
commit
f156580b01
@ -7,6 +7,7 @@
|
||||
#include "Gui.h"
|
||||
#include "Entity.h"
|
||||
#include "Input.h"
|
||||
#include "Event.h"
|
||||
|
||||
struct _CameraData Camera;
|
||||
static struct PickedPos cameraClipPos;
|
||||
|
@ -1,6 +1,5 @@
|
||||
#ifndef CC_GUI_H
|
||||
#define CC_GUI_H
|
||||
#include "Event.h"
|
||||
#include "VertexStructs.h"
|
||||
/* Describes and manages 2D GUI elements on screen.
|
||||
Copyright 2014-2019 ClassiCube | Licensed under BSD-3
|
||||
|
49
src/Input.c
49
src/Input.c
@ -47,6 +47,7 @@ static struct TouchPointer {
|
||||
long id;
|
||||
cc_uint8 type;
|
||||
int begX, begY;
|
||||
TimeMS start;
|
||||
} touches[INPUT_MAX_POINTERS];
|
||||
int Pointers_Count;
|
||||
cc_bool Input_Placing;
|
||||
@ -60,6 +61,11 @@ cc_bool Input_Placing;
|
||||
#define TOUCH_TYPE_BLOCKS 4
|
||||
#define TOUCH_TYPE_ALL (TOUCH_TYPE_GUI | TOUCH_TYPE_CAMERA | TOUCH_TYPE_BLOCKS)
|
||||
|
||||
static void DoDeleteBlock(void);
|
||||
static void DoPlaceBlock(void);
|
||||
static void MouseStatePress(int button);
|
||||
static void MouseStateRelease(int button);
|
||||
|
||||
static cc_bool AnyBlockTouches(void) {
|
||||
int i;
|
||||
for (i = 0; i < Pointers_Count; i++) {
|
||||
@ -75,6 +81,12 @@ void Input_AddTouch(long id, int x, int y) {
|
||||
touches[i].begX = x;
|
||||
touches[i].begY = y;
|
||||
|
||||
touches[i].start = DateTime_CurrentUTC_MS();
|
||||
/* Also set last click time, otherwise quickly tapping */
|
||||
/* sometimes triggers a 'delete' in InputHandler_PickBlocks, */
|
||||
/* and then another 'delete' in CheckBlockTap. */
|
||||
input_lastClick = touches[i].start;
|
||||
|
||||
Pointers_Count++;
|
||||
Pointer_SetPosition(i, x, y);
|
||||
Pointer_SetPressed(i, true);
|
||||
@ -96,7 +108,7 @@ void Input_UpdateTouch(long id, int x, int y) {
|
||||
if (touches[i].type == TOUCH_TYPE_ALL && MovedFromBeg(i, x, y)) {
|
||||
/* Allow a little bit of leeway because though, because devices */
|
||||
/* might still report a few pixels of movement depending on how */
|
||||
/* user is holding the finger down on the toiuch surface */
|
||||
/* user is holding the finger down on the touch surface */
|
||||
touches[i].type = TOUCH_TYPE_CAMERA;
|
||||
}
|
||||
Event_RaiseMove(&PointerEvents.RawMoved, i, x - Pointers[i].x, y - Pointers[i].y);
|
||||
@ -106,12 +118,29 @@ void Input_UpdateTouch(long id, int x, int y) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Quickly tapping should trigger a block place/delete */
|
||||
static void CheckBlockTap(int i) {
|
||||
int btn, pressed;
|
||||
if (DateTime_CurrentUTC_MS() > touches[i].start + 250) return;
|
||||
if (touches[i].type != TOUCH_TYPE_ALL) return;
|
||||
|
||||
btn = Input_Placing ? MOUSE_RIGHT : MOUSE_LEFT;
|
||||
pressed = input_buttonsDown[btn];
|
||||
MouseStatePress(btn);
|
||||
|
||||
if (btn == MOUSE_LEFT) { DoDeleteBlock(); }
|
||||
else { DoPlaceBlock(); }
|
||||
|
||||
if (!pressed) MouseStateRelease(btn);
|
||||
}
|
||||
|
||||
void Input_RemoveTouch(long id, int x, int y) {
|
||||
int i;
|
||||
for (i = 0; i < Pointers_Count; i++) {
|
||||
if (touches[i].id != id) continue;
|
||||
Pointer_SetPosition(i, x, y);
|
||||
Pointer_SetPressed(i, false);
|
||||
CheckBlockTap(i);
|
||||
|
||||
/* found the touch, remove it */
|
||||
for (; i < Pointers_Count - 1; i++) {
|
||||
@ -639,7 +668,7 @@ static cc_bool CheckIsFree(BlockID block) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static void InputHandler_DeleteBlock(void) {
|
||||
static void DoDeleteBlock(void) {
|
||||
IVec3 pos;
|
||||
BlockID old;
|
||||
/* always play delete animations, even if we aren't deleting a block */
|
||||
@ -655,7 +684,7 @@ static void InputHandler_DeleteBlock(void) {
|
||||
Event_RaiseBlock(&UserEvents.BlockChanged, pos, old, BLOCK_AIR);
|
||||
}
|
||||
|
||||
static void InputHandler_PlaceBlock(void) {
|
||||
static void DoPlaceBlock(void) {
|
||||
IVec3 pos;
|
||||
BlockID old, block;
|
||||
pos = Game_SelectedPos.TranslatedPos;
|
||||
@ -674,7 +703,7 @@ static void InputHandler_PlaceBlock(void) {
|
||||
Event_RaiseBlock(&UserEvents.BlockChanged, pos, old, block);
|
||||
}
|
||||
|
||||
static void InputHandler_PickBlock(void) {
|
||||
static void DoPickBlock(void) {
|
||||
IVec3 pos;
|
||||
BlockID cur;
|
||||
pos = Game_SelectedPos.BlockPos;
|
||||
@ -715,11 +744,11 @@ void InputHandler_PickBlocks(void) {
|
||||
}
|
||||
|
||||
if (left) {
|
||||
InputHandler_DeleteBlock();
|
||||
DoDeleteBlock();
|
||||
} else if (right) {
|
||||
InputHandler_PlaceBlock();
|
||||
DoPlaceBlock();
|
||||
} else if (middle) {
|
||||
InputHandler_PickBlock();
|
||||
DoPickBlock();
|
||||
}
|
||||
}
|
||||
|
||||
@ -804,13 +833,13 @@ static cc_bool HandleBlockKey(int key) {
|
||||
|
||||
if (key == KeyBinds[KEYBIND_DELETE_BLOCK]) {
|
||||
MouseStatePress(MOUSE_LEFT);
|
||||
InputHandler_DeleteBlock();
|
||||
DoDeleteBlock();
|
||||
} else if (key == KeyBinds[KEYBIND_PLACE_BLOCK]) {
|
||||
MouseStatePress(MOUSE_RIGHT);
|
||||
InputHandler_PlaceBlock();
|
||||
DoPlaceBlock();
|
||||
} else if (key == KeyBinds[KEYBIND_PICK_BLOCK]) {
|
||||
MouseStatePress(MOUSE_MIDDLE);
|
||||
InputHandler_PickBlock();
|
||||
DoPickBlock();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ void Input_SetPressed(int key, cc_bool pressed);
|
||||
/* Raises InputEvents.Up for each previously pressed button. */
|
||||
void Input_Clear(void);
|
||||
|
||||
/* Whether raw mouse/touch input is being listened for. */
|
||||
/* Whether raw mouse/touch input is currently being listened for. */
|
||||
extern cc_bool Input_RawMode;
|
||||
/* Whether touch input is being used. */
|
||||
extern cc_bool Input_TouchMode;
|
||||
|
15
src/Menus.c
15
src/Menus.c
@ -831,7 +831,7 @@ static int EditHotkeyScreen_KeyPress(void* screen, char keyChar) {
|
||||
static int EditHotkeyScreen_TextChanged(void* screen, const String* str) {
|
||||
#ifdef CC_BUILD_TOUCH
|
||||
struct EditHotkeyScreen* s = (struct EditHotkeyScreen*)screen;
|
||||
InputWidget_SetAndSyncText(&s->input.base, str);
|
||||
InputWidget_SetText(&s->input.base, str);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
@ -1023,7 +1023,7 @@ static int GenLevelScreen_KeyPress(void* screen, char keyChar) {
|
||||
static int GenLevelScreen_TextChanged(void* screen, const String* str) {
|
||||
#ifdef CC_BUILD_TOUCH
|
||||
struct GenLevelScreen* s = (struct GenLevelScreen*)screen;
|
||||
if (s->selected) InputWidget_SetAndSyncText(&s->selected->base, str);
|
||||
if (s->selected) InputWidget_SetText(&s->selected->base, str);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
@ -1377,7 +1377,7 @@ static int SaveLevelScreen_TextChanged(void* screen, const String* str) {
|
||||
#ifdef CC_BUILD_TOUCH
|
||||
struct SaveLevelScreen* s = (struct SaveLevelScreen*)screen;
|
||||
SaveLevelScreen_RemoveOverwrites(s);
|
||||
InputWidget_SetAndSyncText(&s->input.base, str);
|
||||
InputWidget_SetText(&s->input.base, str);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
@ -2055,7 +2055,7 @@ static int MenuOptionsScreen_KeyPress(void* screen, char keyChar) {
|
||||
static int MenuOptionsScreen_TextChanged(void* screen, const String* str) {
|
||||
#ifdef CC_BUILD_TOUCH
|
||||
struct MenuOptionsScreen* s = (struct MenuOptionsScreen*)screen;
|
||||
if (s->activeI >= 0) InputWidget_SetAndSyncText(&s->input.base, str);
|
||||
if (s->activeI >= 0) InputWidget_SetText(&s->input.base, str);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
@ -2112,14 +2112,11 @@ static void MenuOptionsScreen_OK(void* screen, void* widget) {
|
||||
static void MenuOptionsScreen_Default(void* screen, void* widget) {
|
||||
String value; char valueBuffer[STRING_SIZE];
|
||||
struct MenuOptionsScreen* s = (struct MenuOptionsScreen*)screen;
|
||||
struct MenuInputDesc* desc;
|
||||
struct MenuInputDesc* desc = &s->descs[s->activeI];
|
||||
|
||||
desc = &s->descs[s->activeI];
|
||||
String_InitArray(value, valueBuffer);
|
||||
desc->VTABLE->GetDefault(desc, &value);
|
||||
|
||||
InputWidget_Clear(&s->input.base);
|
||||
InputWidget_AppendString(&s->input.base, &value);
|
||||
InputWidget_SetText(&s->input.base, &value);
|
||||
}
|
||||
|
||||
static void MenuOptionsScreen_Bool(void* screen, void* widget) {
|
||||
|
216
src/Screens.c
216
src/Screens.c
@ -324,6 +324,9 @@ static struct ChatScreen {
|
||||
struct ChatInputWidget input;
|
||||
struct TextGroupWidget status, bottomRight, chat, clientStatus;
|
||||
struct SpecialInputWidget altText;
|
||||
#ifdef CC_BUILD_TOUCH
|
||||
struct ButtonWidget send, cancel;
|
||||
#endif
|
||||
|
||||
struct Texture statusTextures[CHAT_MAX_STATUS];
|
||||
struct Texture bottomRightTextures[CHAT_MAX_BOTTOMRIGHT];
|
||||
@ -616,6 +619,12 @@ static void ChatScreen_DrawChat(struct ChatScreen* s, double delta) {
|
||||
if (s->altText.active) {
|
||||
Elem_Render(&s->altText, delta);
|
||||
}
|
||||
|
||||
#ifdef CC_BUILD_TOUCH
|
||||
if (!Input_TouchMode) return;
|
||||
Elem_Render(&s->send, delta);
|
||||
Elem_Render(&s->cancel, delta);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -638,6 +647,7 @@ static void ChatScreen_ContextLost(void* screen) {
|
||||
struct ChatScreen* s = (struct ChatScreen*)screen;
|
||||
Font_Free(&s->playerFont);
|
||||
ChatScreen_FreeChatFonts(s);
|
||||
if (s->showingList) Elem_Free(&s->playerList);
|
||||
|
||||
Elem_TryFree(&s->chat);
|
||||
Elem_TryFree(&s->input.base);
|
||||
@ -647,7 +657,10 @@ static void ChatScreen_ContextLost(void* screen) {
|
||||
Elem_TryFree(&s->clientStatus);
|
||||
Elem_TryFree(&s->announcement);
|
||||
|
||||
if (s->showingList) Elem_Free(&s->playerList);
|
||||
#ifdef CC_BUILD_TOUCH
|
||||
Elem_TryFree(&s->send);
|
||||
Elem_TryFree(&s->cancel);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void ChatScreen_RemakePlayerList(struct ChatScreen* s) {
|
||||
@ -660,6 +673,7 @@ static void ChatScreen_RemakePlayerList(struct ChatScreen* s) {
|
||||
static void ChatScreen_ContextRecreated(void* screen) {
|
||||
struct ChatScreen* s = (struct ChatScreen*)screen;
|
||||
int size = Drawer2D_BitmappedText ? 16 : 11;
|
||||
struct FontDesc font;
|
||||
Drawer2D_MakeFont(&s->playerFont, size, FONT_STYLE_NORMAL);
|
||||
ChatScreen_ChatUpdateFont(s);
|
||||
|
||||
@ -667,6 +681,14 @@ static void ChatScreen_ContextRecreated(void* screen) {
|
||||
Widget_Layout(&s->hotbar);
|
||||
ChatScreen_ChatUpdateLayout(s);
|
||||
if (s->showingList) ChatScreen_RemakePlayerList(s);
|
||||
|
||||
#ifdef CC_BUILD_TOUCH
|
||||
if (!Input_TouchMode) return;
|
||||
Drawer2D_MakeFont(&font, 16, FONT_STYLE_BOLD);
|
||||
ButtonWidget_SetConst(&s->send, "Send", &font);
|
||||
ButtonWidget_SetConst(&s->cancel, "Cancel", &font);
|
||||
Font_Free(&font);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void ChatScreen_BuildMesh(void* screen) { }
|
||||
@ -678,6 +700,12 @@ static void ChatScreen_Layout(void* screen) {
|
||||
if (ChatScreen_ChatUpdateFont(s)) ChatScreen_Redraw(s);
|
||||
ChatScreen_ChatUpdateLayout(s);
|
||||
if (s->showingList) Widget_Layout(&s->playerList);
|
||||
|
||||
#ifdef CC_BUILD_TOUCH
|
||||
if (!Input_TouchMode) return;
|
||||
Widget_Layout(&s->send);
|
||||
Widget_Layout(&s->cancel);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int ChatScreen_KeyPress(void* screen, char keyChar) {
|
||||
@ -699,7 +727,7 @@ static int ChatScreen_TextChanged(void* screen, const String* str) {
|
||||
struct ChatScreen* s = (struct ChatScreen*)screen;
|
||||
if (!s->grabsInput) return false;
|
||||
|
||||
InputWidget_SetAndSyncText(&s->input.base, str);
|
||||
InputWidget_SetText(&s->input.base, str);
|
||||
ChatScreen_UpdateChatYOffsets(s);
|
||||
#endif
|
||||
return true;
|
||||
@ -806,6 +834,15 @@ static int ChatScreen_PointerDown(void* screen, int id, int x, int y) {
|
||||
|
||||
if (Game_HideGui) return false;
|
||||
|
||||
#ifdef CC_BUILD_TOUCH
|
||||
if (Widget_Contains(&s->send, x, y)) {
|
||||
ChatScreen_EnterChatInput(s, false); return true;
|
||||
}
|
||||
if (Widget_Contains(&s->cancel, x, y)) {
|
||||
ChatScreen_EnterChatInput(s, true); return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!Widget_Contains(&s->chat, x, y)) {
|
||||
if (s->altText.active && Widget_Contains(&s->altText, x, y)) {
|
||||
Elem_HandlesPointerDown(&s->altText, id, x, y);
|
||||
@ -842,6 +879,12 @@ static void ChatScreen_Init(void* screen) {
|
||||
Event_RegisterInt(&TabListEvents.Added, s, ChatScreen_TabEntryAdded);
|
||||
Event_RegisterInt(&TabListEvents.Changed, s, ChatScreen_TabEntryChanged);
|
||||
Event_RegisterInt(&TabListEvents.Removed, s, ChatScreen_TabEntryRemoved);
|
||||
|
||||
#ifdef CC_BUILD_TOUCH
|
||||
if (!Input_TouchMode) return;
|
||||
ButtonWidget_Make(&s->send, 100, NULL, ANCHOR_MAX, ANCHOR_MIN, 10, 10);
|
||||
ButtonWidget_Make(&s->cancel, 100, NULL, ANCHOR_MAX, ANCHOR_MIN, 10, 60);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void ChatScreen_Render(void* screen, double delta) {
|
||||
@ -922,7 +965,7 @@ void ChatScreen_OpenInput(const String* text) {
|
||||
|
||||
void ChatScreen_AppendInput(const String* text) {
|
||||
struct ChatScreen* s = &ChatScreen_Instance;
|
||||
InputWidget_AppendString(&s->input.base, text);
|
||||
InputWidget_AppendText(&s->input.base, text);
|
||||
ChatScreen_UpdateChatYOffsets(s);
|
||||
}
|
||||
|
||||
@ -1025,32 +1068,27 @@ static int InventoryScreen_KeyDown(void* screen, int key) {
|
||||
Gui_Remove((struct Screen*)s);
|
||||
} else if (Elem_HandlesKeyDown(table, key)) {
|
||||
} else {
|
||||
struct ChatScreen* hud = (struct ChatScreen*)Gui_Chat;
|
||||
return Elem_HandlesKeyDown(&hud->hotbar, key);
|
||||
return Elem_HandlesKeyDown(&Gui_Chat->hotbar, key);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int InventoryScreen_KeyUp(void* screen, int key) {
|
||||
struct InventoryScreen* s = (struct InventoryScreen*)screen;
|
||||
struct ChatScreen* hud;
|
||||
|
||||
if (key == KeyBinds[KEYBIND_INVENTORY]) {
|
||||
s->releasedInv = true; return true;
|
||||
}
|
||||
|
||||
hud = (struct ChatScreen*)Gui_Chat;
|
||||
return Elem_HandlesKeyUp(&hud->hotbar, key);
|
||||
return Elem_HandlesKeyUp(&Gui_Chat->hotbar, key);
|
||||
}
|
||||
|
||||
static int InventoryScreen_PointerDown(void* screen, int id, int x, int y) {
|
||||
struct InventoryScreen* s = (struct InventoryScreen*)screen;
|
||||
struct TableWidget* table = &s->table;
|
||||
struct ChatScreen* hud = (struct ChatScreen*)Gui_Chat;
|
||||
cc_bool handled, hotbar;
|
||||
|
||||
if (table->scroll.draggingId == id) return true;
|
||||
if (Elem_HandlesPointerDown(&hud->hotbar, id, x, y)) return true;
|
||||
if (Elem_HandlesPointerDown(&Gui_Chat->hotbar, id, x, y)) return true;
|
||||
handled = Elem_HandlesPointerDown(table, id, x, y);
|
||||
|
||||
if (!handled || table->pendingClose) {
|
||||
@ -1516,128 +1554,91 @@ void DisconnectScreen_Show(const String* title, const String* message) {
|
||||
#ifdef CC_BUILD_TOUCH
|
||||
static struct TouchScreen {
|
||||
Screen_Body
|
||||
int numButtons, layout;
|
||||
cc_uint8 binds[10];
|
||||
cc_uint8 binds[7];
|
||||
struct FontDesc font;
|
||||
struct ButtonWidget buttons[10];
|
||||
} TouchScreen_Instance;
|
||||
struct ButtonWidget btns[7];
|
||||
} TouchScreen;
|
||||
|
||||
static struct Widget* touch_widgets[7] = {
|
||||
(struct Widget*)&TouchScreen.btns[0], (struct Widget*)&TouchScreen.btns[1],
|
||||
(struct Widget*)&TouchScreen.btns[2], (struct Widget*)&TouchScreen.btns[3],
|
||||
(struct Widget*)&TouchScreen.btns[4], (struct Widget*)&TouchScreen.btns[5],
|
||||
(struct Widget*)&TouchScreen.btns[6],
|
||||
};
|
||||
#define TOUCH_MAX_VERTICES (7 * BUTTONWIDGET_MAX)
|
||||
|
||||
static const struct TouchBindDesc {
|
||||
const char* text;
|
||||
cc_uint8 bind, width;
|
||||
cc_int16 xOffset, yOffset;
|
||||
} touchDescs[8] = {
|
||||
{ "<", KEYBIND_LEFT, 40, 150, 50 },
|
||||
{ ">", KEYBIND_RIGHT, 40, 10, 50 },
|
||||
{ "^", KEYBIND_FORWARD, 40, 80, 10 },
|
||||
{ "\\/", KEYBIND_BACK, 40, 80, 90 },
|
||||
{ "Jump", KEYBIND_JUMP, 100, 50, 150 },
|
||||
{ "Mode", KEYBIND_COUNT, 100, 50, 190 },
|
||||
{ "More", KEYBIND_COUNT, 100, 50, 230 },
|
||||
/* Chat labels */
|
||||
{ "Send ", KEYBIND_SEND_CHAT, 100, 50, 10 },
|
||||
} touchDescs[7] = {
|
||||
{ "<", KEYBIND_LEFT, 40, 150, 50 },
|
||||
{ ">", KEYBIND_RIGHT, 40, 10, 50 },
|
||||
{ "^", KEYBIND_FORWARD, 40, 80, 10 },
|
||||
{ "\\/", KEYBIND_BACK, 40, 80, 90 },
|
||||
{ "Jump", KEYBIND_JUMP, 100, 50, 150 },
|
||||
{ "", KEYBIND_COUNT, 100, 50, 190 },
|
||||
{ "More", KEYBIND_COUNT, 100, 50, 230 },
|
||||
};
|
||||
|
||||
#define TOUCH_LAYOUT_FULL 0
|
||||
#define TOUCH_LAYOUT_CHAT 1
|
||||
#define TOUCH_LAYOUT_NONE 2
|
||||
|
||||
CC_NOINLINE static int CalcTouchMenuLayout(void) {
|
||||
struct Screen* grabbed = Gui_GetInputGrab();
|
||||
if (!grabbed) return TOUCH_LAYOUT_FULL;
|
||||
if (grabbed == &ChatScreen_Instance) return TOUCH_LAYOUT_CHAT;
|
||||
return TOUCH_LAYOUT_NONE;
|
||||
}
|
||||
|
||||
static void TouchScreen_ContextLost(void* screen) {
|
||||
struct TouchScreen* s = (struct TouchScreen*)screen;
|
||||
int i;
|
||||
Font_Free(&s->font);
|
||||
|
||||
for (i = 0; i < s->numButtons; i++) {
|
||||
Elem_Free(&s->buttons[i]);
|
||||
}
|
||||
Screen_ContextLost(screen);
|
||||
}
|
||||
|
||||
CC_NOINLINE static void TouchScreen_Set(struct TouchScreen* s, int i, const char* text, KeyBind bind) {
|
||||
ButtonWidget_SetConst(&s->buttons[i], text, &s->font);
|
||||
s->binds[i] = bind;
|
||||
static void TouchScreen_UpdateModeText(void* screen) {
|
||||
struct TouchScreen* s = (struct TouchScreen*)screen;
|
||||
ButtonWidget_SetConst(&s->btns[5], Input_Placing ? "Place" : "Delete", &s->font);
|
||||
}
|
||||
|
||||
static void TouchScreen_ModeClick(void* s, void* w) { Input_Placing = !Input_Placing; }
|
||||
static void TouchScreen_ModeClick(void* s, void* w) {
|
||||
Input_Placing = !Input_Placing;
|
||||
TouchScreen_UpdateModeText(s);
|
||||
}
|
||||
static void TouchScreen_MoreClick(void* s, void* w) { TouchMoreOverlay_Show(); }
|
||||
|
||||
static void TouchScreen_ContextRecreated(void* screen) {
|
||||
struct TouchScreen* s = (struct TouchScreen*)screen;
|
||||
const struct TouchBindDesc* desc;
|
||||
int i, offset = 0;
|
||||
int i;
|
||||
|
||||
Drawer2D_MakeFont(&s->font, 16, FONT_STYLE_BOLD);
|
||||
s->layout = CalcTouchMenuLayout();
|
||||
s->numButtons = 0;
|
||||
s->vb = Gfx_CreateDynamicVb(VERTEX_FORMAT_P3FT2FC4B, TOUCH_MAX_VERTICES);
|
||||
|
||||
switch (s->layout) {
|
||||
case TOUCH_LAYOUT_FULL:
|
||||
s->numButtons = 7;
|
||||
break;
|
||||
case TOUCH_LAYOUT_CHAT:
|
||||
offset = 7;
|
||||
s->numButtons = 1;
|
||||
break;
|
||||
for (i = 0; i < s->numWidgets; i++) {
|
||||
desc = &touchDescs[i];
|
||||
ButtonWidget_SetConst(&s->btns[i], desc->text, &s->font);
|
||||
}
|
||||
|
||||
for (i = 0; i < s->numButtons; i++) {
|
||||
desc = &touchDescs[i + offset];
|
||||
ButtonWidget_Make(&s->buttons[i], desc->width, NULL, ANCHOR_MAX, ANCHOR_MIN,
|
||||
desc->xOffset, desc->yOffset);
|
||||
ButtonWidget_SetConst(&s->buttons[i], desc->text, &s->font);
|
||||
s->binds[i] = desc->bind;
|
||||
}
|
||||
|
||||
TouchScreen_UpdateModeText(s);
|
||||
/* TODO: Mode should display 'Place' or 'Delete' */
|
||||
/* TODO: this is pretty nasty hacky. rewrite! */
|
||||
s->buttons[5].MenuClick = TouchScreen_ModeClick;
|
||||
s->buttons[6].MenuClick = TouchScreen_MoreClick;
|
||||
}
|
||||
|
||||
static void TouchScreen_Render(void* screen, double delta) {
|
||||
struct TouchScreen* s = (struct TouchScreen*)screen;
|
||||
int i;
|
||||
if (Gui_GetInputGrab()) return;
|
||||
|
||||
Gfx_SetTexturing(true);
|
||||
for (i = 0; i < s->numButtons; i++) {
|
||||
Elem_Render(&s->buttons[i], delta);
|
||||
}
|
||||
Screen_Render2Widgets(screen, delta);
|
||||
Gfx_SetTexturing(false);
|
||||
|
||||
i = CalcTouchMenuLayout();
|
||||
/* TODO: AWFUL AWFUL HACK */
|
||||
/* use guiEvents instead */
|
||||
if (i != s->layout) Gui_Refresh(s);
|
||||
}
|
||||
|
||||
static void TouchScreen_Layout(void* screen) {
|
||||
struct TouchScreen* s = (struct TouchScreen*)screen;
|
||||
int i;
|
||||
for (i = 0; i < s->numButtons; i++) {
|
||||
Widget_Layout(&s->buttons[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static int TouchScreen_PointerDown(void* screen, int id, int x, int y) {
|
||||
struct TouchScreen* s = (struct TouchScreen*)screen;
|
||||
int i;
|
||||
//Chat_Add1("POINTER DOWN: %i", &id);
|
||||
if (Gui_GetInputGrab()) return false;
|
||||
|
||||
for (i = 0; i < s->numButtons; i++) {
|
||||
if (!Widget_Contains(&s->buttons[i], x, y)) continue;
|
||||
for (i = 0; i < s->numWidgets; i++) {
|
||||
if (!Widget_Contains(&s->btns[i], x, y)) continue;
|
||||
|
||||
if (s->binds[i] < KEYBIND_COUNT) {
|
||||
Input_SetPressed(KeyBinds[s->binds[i]], true);
|
||||
} else {
|
||||
s->buttons[i].MenuClick(screen, &s->buttons[i]);
|
||||
s->btns[i].MenuClick(screen, &s->btns[i]);
|
||||
}
|
||||
s->buttons[i].active |= id;
|
||||
s->btns[i].active |= id;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -1648,29 +1649,54 @@ static int TouchScreen_PointerUp(void* screen, int id, int x, int y) {
|
||||
int i;
|
||||
//Chat_Add1("POINTER UP: %i", &id);
|
||||
|
||||
for (i = 0; i < s->numButtons; i++) {
|
||||
if (!(s->buttons[i].active & id)) continue;
|
||||
for (i = 0; i < s->numWidgets; i++) {
|
||||
if (!(s->btns[i].active & id)) continue;
|
||||
|
||||
if (s->binds[i] < KEYBIND_COUNT) {
|
||||
Input_SetPressed(KeyBinds[s->binds[i]], false);
|
||||
}
|
||||
s->buttons[i].active &= ~id;
|
||||
s->btns[i].active &= ~id;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void TouchScreen_BuildMesh(void* screen) { }
|
||||
static void TouchScreen_BuildMesh(void* screen) {
|
||||
struct Screen* s = (struct Screen*)screen;
|
||||
VertexP3fT2fC4b vertices[TOUCH_MAX_VERTICES];
|
||||
|
||||
Screen_BuildMesh(screen, vertices);
|
||||
Gfx_SetDynamicVbData(s->vb, vertices, TOUCH_MAX_VERTICES);
|
||||
}
|
||||
|
||||
static void TouchScreen_Init(void* screen) {
|
||||
struct TouchScreen* s = (struct TouchScreen*)screen;
|
||||
const struct TouchBindDesc* desc;
|
||||
int i;
|
||||
|
||||
s->widgets = touch_widgets;
|
||||
s->numWidgets = Array_Elems(touch_widgets);
|
||||
|
||||
for (i = 0; i < s->numWidgets; i++) {
|
||||
desc = &touchDescs[i];
|
||||
ButtonWidget_Make(&s->btns[i], desc->width, NULL, ANCHOR_MAX, ANCHOR_MIN,
|
||||
desc->xOffset, desc->yOffset);
|
||||
s->binds[i] = desc->bind;
|
||||
}
|
||||
|
||||
s->btns[5].MenuClick = TouchScreen_ModeClick;
|
||||
s->btns[6].MenuClick = TouchScreen_MoreClick;
|
||||
}
|
||||
|
||||
static const struct ScreenVTABLE TouchScreen_VTABLE = {
|
||||
Screen_NullFunc, Screen_NullUpdate, Screen_NullFunc,
|
||||
TouchScreen_Init, Screen_NullUpdate, Screen_NullFunc,
|
||||
TouchScreen_Render, TouchScreen_BuildMesh,
|
||||
Screen_FInput, Screen_FInput, Screen_FKeyPress, Screen_FText,
|
||||
TouchScreen_PointerDown, TouchScreen_PointerUp, Screen_FPointer, Screen_FMouseScroll,
|
||||
TouchScreen_Layout, TouchScreen_ContextLost, TouchScreen_ContextRecreated
|
||||
Screen_Layout, TouchScreen_ContextLost, TouchScreen_ContextRecreated
|
||||
};
|
||||
void TouchScreen_Show(void) {
|
||||
struct TouchScreen* s = &TouchScreen_Instance;
|
||||
struct TouchScreen* s = &TouchScreen;
|
||||
s->VTABLE = &TouchScreen_VTABLE;
|
||||
|
||||
if (!Input_TouchMode) return;
|
||||
|
@ -1060,7 +1060,7 @@ static cc_bool InputWidget_TryAppendChar(struct InputWidget* w, char c) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void InputWidget_AppendString(struct InputWidget* w, const String* text) {
|
||||
void InputWidget_AppendText(struct InputWidget* w, const String* text) {
|
||||
int i, appended = 0;
|
||||
for (i = 0; i < text->length; i++) {
|
||||
if (InputWidget_TryAppendChar(w, text->buffer[i])) appended++;
|
||||
@ -1174,7 +1174,7 @@ static void InputWidget_EndKey(struct InputWidget* w) {
|
||||
}
|
||||
|
||||
static void InputWidget_CopyFromClipboard(String* text, void* w) {
|
||||
InputWidget_AppendString((struct InputWidget*)w, text);
|
||||
InputWidget_AppendText((struct InputWidget*)w, text);
|
||||
}
|
||||
|
||||
static cc_bool InputWidget_OtherKey(struct InputWidget* w, int key) {
|
||||
@ -1204,12 +1204,14 @@ void InputWidget_UpdateText(struct InputWidget* w) {
|
||||
InputWidget_CalculateLineSizes(w);
|
||||
w->RemakeTexture(w);
|
||||
InputWidget_UpdateCaret(w);
|
||||
Window_SetKeyboardText(&w->text);
|
||||
}
|
||||
|
||||
void InputWidget_SetAndSyncText(struct InputWidget* w, const String* str) {
|
||||
void InputWidget_SetText(struct InputWidget* w, const String* str) {
|
||||
InputWidget_Clear(w);
|
||||
InputWidget_AppendString(w, str);
|
||||
Window_SetKeyboardText(&w->text);
|
||||
InputWidget_AppendText(w, str);
|
||||
/* If text is empty, InputWidget_UpdateText won't have been called */
|
||||
if (!w->text.length) Window_SetKeyboardText(&w->text);
|
||||
}
|
||||
|
||||
static void InputWidget_Free(void* widget) {
|
||||
@ -1723,7 +1725,7 @@ static void ChatInputWidget_TabKey(struct InputWidget* w) {
|
||||
|
||||
if (w->caretPos != -1) w->caretPos -= len;
|
||||
name = TabList_UNSAFE_GetPlayer(matches[0]);
|
||||
InputWidget_AppendString(w, &name);
|
||||
InputWidget_AppendText(w, &name);
|
||||
} else if (numMatches > 1) {
|
||||
String_InitArray(str, strBuffer);
|
||||
String_Format1(&str, "&e%i matching names: ", &numMatches);
|
||||
@ -2573,7 +2575,7 @@ static void SpecialInputWidget_IntersectsBody(struct SpecialInputWidget* w, int
|
||||
|
||||
/* TODO: Not be so hacky */
|
||||
if (w->selectedIndex == 0) str.length = 2;
|
||||
InputWidget_AppendString(w->target, &str);
|
||||
InputWidget_AppendText(w->target, &str);
|
||||
}
|
||||
|
||||
static void SpecialInputTab_Init(struct SpecialInputTab* tab, STRING_REF String* title, int itemsPerRow, int charsPerItem, STRING_REF String* contents) {
|
||||
|
@ -130,16 +130,19 @@ struct InputWidget {
|
||||
/* Removes all characters and then deletes the input texture. */
|
||||
CC_NOINLINE void InputWidget_Clear(struct InputWidget* w);
|
||||
/* Tries appending all characters from the given string, then update the input texture. */
|
||||
CC_NOINLINE void InputWidget_AppendString(struct InputWidget* w, const String* text);
|
||||
CC_NOINLINE void InputWidget_AppendText(struct InputWidget* w, const String* text);
|
||||
/* Tries appending the given character, then updates the input texture. */
|
||||
CC_NOINLINE void InputWidget_Append(struct InputWidget* w, char c);
|
||||
/* Redraws text and recalculates associated state. */
|
||||
/* Also calls Window_SetKeyboardText with the text in the input widget. */
|
||||
/* This way native text input state stays synchronised with the input widget. */
|
||||
/* (e.g. may only accept numerical input, so 'c' gets stripped from str) */
|
||||
CC_NOINLINE void InputWidget_UpdateText(struct InputWidget* w);
|
||||
/* Shorthand for InputWidget_Clear followed by InputWidget_AppendString, */
|
||||
/* Shorthand for InputWidget_Clear followed by InputWidget_AppendText, */
|
||||
/* then calls Window_SetKeyboardText with the text in the input widget. */
|
||||
/* This way native text input state stays synchronised with the input widget. */
|
||||
/* (e.g. may only accept numerical input, so 'c' gets stripped from str) */
|
||||
CC_NOINLINE void InputWidget_SetAndSyncText(struct InputWidget* w, const String* str);
|
||||
CC_NOINLINE void InputWidget_SetText(struct InputWidget* w, const String* str);
|
||||
|
||||
|
||||
struct MenuInputDesc;
|
||||
|
Loading…
x
Reference in New Issue
Block a user