diff --git a/src/Gui.c b/src/Gui.c index 7a6fba852..f261d19e0 100644 --- a/src/Gui.c +++ b/src/Gui.c @@ -83,6 +83,9 @@ bool Gui_ContainsPointers(int x, int y, int width, int height) { void Gui_ShowDefault(void) { StatusScreen_Show(); HUDScreen_Show(); +#ifdef CC_BUILD_TOUCH + TouchScreen_Show(); +#endif } static void Gui_ContextLost(void* obj) { diff --git a/src/Gui.h b/src/Gui.h index 62cdc1fd6..73e68ab78 100644 --- a/src/Gui.h +++ b/src/Gui.h @@ -94,12 +94,13 @@ extern GfxResourceID Gui_GuiTex, Gui_GuiClassicTex, Gui_IconsTex; /* Higher priority handles input first and draws on top */ enum GuiPriority { - GUI_PRIORITY_DISCONNECT = 50, - GUI_PRIORITY_OLDLOADING = 45, - GUI_PRIORITY_URLWARNING = 40, - GUI_PRIORITY_TEXPACK = 35, - GUI_PRIORITY_TEXIDS = 30, - GUI_PRIORITY_MENU = 25, + GUI_PRIORITY_DISCONNECT = 55, + GUI_PRIORITY_OLDLOADING = 50, + GUI_PRIORITY_URLWARNING = 45, + GUI_PRIORITY_TEXPACK = 40, + GUI_PRIORITY_TEXIDS = 35, + GUI_PRIORITY_MENU = 30, + GUI_PRIORITY_TOUCH = 25, GUI_PRIORITY_INVENTORY = 20, GUI_PRIORITY_STATUS = 15, GUI_PRIORITY_HUD = 10, diff --git a/src/Input.c b/src/Input.c index d7d22c5e9..4d01b5255 100644 --- a/src/Input.c +++ b/src/Input.c @@ -79,7 +79,7 @@ void Input_SetPressed(Key key, bool pressed) { /* don't allow multiple left mouse down events */ if (key != KEY_LMOUSE || pressed == wasPressed) return; - Mouse_SetPressed(0, pressed); + Pointer_SetPressed(0, pressed); } void Key_Clear(void) { @@ -98,7 +98,7 @@ float Mouse_Wheel; int Mouse_X, Mouse_Y; struct Pointer Pointers[INPUT_MAX_POINTERS]; -void Mouse_SetPressed(int idx, bool pressed) { +void Pointer_SetPressed(int idx, bool pressed) { if (pressed) { Event_RaiseInt(&PointerEvents.Down, idx); } else { @@ -112,11 +112,13 @@ void Mouse_SetWheel(float wheel) { Event_RaiseFloat(&InputEvents.Wheel, delta); } -void Mouse_SetPosition(int x, int y) { +void Pointer_SetPosition(int idx, int x, int y) { int deltaX = x - Mouse_X, deltaY = y - Mouse_Y; Mouse_X = x; Mouse_Y = y; - Pointers[0].x = x; Pointers[0].y = y; - Event_RaiseMove(&PointerEvents.Moved, 0, deltaX, deltaY); + if (x == Pointers[idx].x && y == Pointers[idx].y) return; + /* TODO: reset to -1, -1 when pointer is removed */ + Pointers[idx].x = x; Pointers[idx].y = y; + Event_RaiseMove(&PointerEvents.Moved, idx, deltaX, deltaY); } diff --git a/src/Input.h b/src/Input.h index 676df0a42..dc6e9f6a1 100644 --- a/src/Input.h +++ b/src/Input.h @@ -83,11 +83,11 @@ extern struct Pointer { int x, y; } Pointers[INPUT_MAX_POINTERS]; extern int Mouse_X, Mouse_Y; /* Raises PointerEvents.Up or PointerEvents.Down. */ -void Mouse_SetPressed(int idx, bool pressed); +void Pointer_SetPressed(int idx, bool pressed); /* Sets wheel position of the mouse, always raising InputEvents.Wheel. */ void Mouse_SetWheel(float wheel); -/* Sets X and Y position of the mouse, always raising PointerEvents.Moved. */ -void Mouse_SetPosition(int x, int y); +/* Sets X and Y position of the given pointer, always raising PointerEvents.Moved. */ +void Pointer_SetPosition(int idx, int x, int y); /* Enumeration of all key bindings. */ diff --git a/src/MapRenderer.c b/src/MapRenderer.c index aebd13116..821c511d8 100644 --- a/src/MapRenderer.c +++ b/src/MapRenderer.c @@ -55,7 +55,7 @@ struct ChunkInfo* MapRenderer_GetChunk(int cx, int cy, int cz) { void ChunkInfo_Reset(struct ChunkInfo* chunk, int x, int y, int z) { chunk->CentreX = x + 8; chunk->CentreY = y + 8; chunk->CentreZ = z + 8; #ifndef CC_BUILD_GL11 - chunk->Vb = GFX_NULL; + chunk->Vb = 0; #endif chunk->Visible = true; chunk->Empty = false; diff --git a/src/Screens.c b/src/Screens.c index 39b38e198..1f743f69c 100644 --- a/src/Screens.c +++ b/src/Screens.c @@ -784,6 +784,7 @@ static void HUDScreen_EnterChatInput(struct HUDScreen* s, bool close) { s->grabsInput = false; Camera_CheckFocus(); + Window_CloseKeyboard(); if (close) InputWidget_Clear(&s->input.base); input = &s->input.base; @@ -1207,6 +1208,7 @@ void HUDScreen_OpenInput(const String* text) { s->suppressNextPress = true; s->grabsInput = true; Camera_CheckFocus(); + Window_OpenKeyboard(); String_Copy(&s->input.base.text, text); InputWidget_UpdateText(&s->input.base); @@ -1398,3 +1400,157 @@ void DisconnectScreen_Show(const String* title, const String* message) { while (Gui_ScreensCount) Gui_Remove(Gui_Screens[0]); Gui_Replace((struct Screen*)s, GUI_PRIORITY_DISCONNECT); } + + +/*########################################################################################################################* +*--------------------------------------------------------TouchScreen------------------------------------------------------* +*#########################################################################################################################*/ +#ifdef CC_BUILD_TOUCH +static struct TouchScreen { + Screen_Layout + int numButtons, layout; + cc_uint8 binds[10]; + struct FontDesc font; + struct ButtonWidget buttons[10]; +} TouchScreen_Instance; + +static const struct TouchBindDesc { + const char* text; + cc_uint8 bind, width; + cc_int16 xOffset, yOffset; +} touchDescs[11] = { + { "<", 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, 50 }, + { "Chat", KEYBIND_CHAT, 100, 50, 150 }, + { "Inv", KEYBIND_INVENTORY, 100, 50, 190 }, + { "Speed", KEYBIND_SPEED, 100, 50, 230 }, + { "Noclip", KEYBIND_NOCLIP, 100, 50, 270 }, + { "Fly", KEYBIND_FLY, 100, 50, 310 }, + /* Chat labels */ + { "Send ", KEYBIND_SEND_CHAT, 100, 50, 10 }, +}; + +#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 == &HUDScreen_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]); + } +} + +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_ContextRecreated(void* screen) { + struct TouchScreen* s = (struct TouchScreen*)screen; + const struct TouchBindDesc* desc; + int i, offset = 0; + + Drawer2D_MakeFont(&s->font, 16, FONT_STYLE_BOLD); + s->layout = CalcTouchMenuLayout(); + s->numButtons = 0; + + switch (s->layout) { + case TOUCH_LAYOUT_FULL: + s->numButtons = 10; + break; + case TOUCH_LAYOUT_CHAT: + offset = 10; + s->numButtons = 1; + break; + } + + 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; + } +} + +static void TouchScreen_Render(void* screen, double delta) { + struct TouchScreen* s = (struct TouchScreen*)screen; + int i; + + Gfx_SetTexturing(true); + for (i = 0; i < s->numButtons; i++) { + Elem_Render(&s->buttons[i], delta); + } + Gfx_SetTexturing(false); + + i = CalcTouchMenuLayout(); + /* TODO: AWFUL AWFUL HACK */ + /* use guiEvents instead */ + if (i != s->layout) Gui_Refresh(s); +} + +static void TouchScreen_OnResize(void* screen) { + struct TouchScreen* s = (struct TouchScreen*)screen; + int i; + for (i = 0; i < s->numButtons; i++) { + Widget_Reposition(&s->buttons[i]); + } +} + +static bool TouchScreen_PointerDown(void* screen, int id, int x, int y) { + struct TouchScreen* s = (struct TouchScreen*)screen; + int i; + //Chat_Add1("POINTER DOWN: %i", &id); + + for (i = 0; i < s->numButtons; i++) { + if (!Widget_Contains(&s->buttons[i], x, y)) continue; + + Input_SetPressed(KeyBinds[s->binds[i]], true); + s->buttons[i].active |= id; + return true; + } + return false; +} + +static bool TouchScreen_PointerUp(void* screen, int id, int x, int y) { + struct TouchScreen* s = (struct TouchScreen*)screen; + int i; + //Chat_Add1("POINTER UP: %i", &id); + + for (i = 0; i < s->numButtons; i++) { + if (!(s->buttons[i].active & id)) continue; + + Input_SetPressed(KeyBinds[s->binds[i]], false); + s->buttons[i].active &= ~id; + return true; + } + return false; +} + +static const struct ScreenVTABLE TouchScreen_VTABLE = { + Screen_NullFunc, TouchScreen_Render, Screen_NullFunc, + Screen_FKey, Screen_FKey, Screen_FKeyPress, + TouchScreen_PointerDown, TouchScreen_PointerUp, Screen_FPointerMove, Screen_FMouseScroll, + TouchScreen_OnResize, TouchScreen_ContextLost, TouchScreen_ContextRecreated +}; +void TouchScreen_Show(void) { + struct TouchScreen* s = &TouchScreen_Instance; + s->VTABLE = &TouchScreen_VTABLE; + /* TODO: if Window_TouchMode */ + Gui_Replace((struct Screen*)s, GUI_PRIORITY_TOUCH); +} +#endif diff --git a/src/Screens.h b/src/Screens.h index a56906411..682c9e0ad 100644 --- a/src/Screens.h +++ b/src/Screens.h @@ -27,6 +27,9 @@ void LoadingScreen_Show(const String* title, const String* message); void GeneratingScreen_Show(void); void HUDScreen_Show(void); void DisconnectScreen_Show(const String* title, const String* message); +#ifdef CC_BUILD_TOUCH +void TouchScreen_Show(void); +#endif /* Raw pointer to loading screen. DO NOT USE THIS. Use LoadingScreen_MakeInstance() */ extern struct Screen* LoadingScreen_UNSAFE_RawPointer; diff --git a/src/Window.c b/src/Window.c index 3ea24cb8a..6a71a5bfd 100644 --- a/src/Window.c +++ b/src/Window.c @@ -99,13 +99,19 @@ static struct TouchData { long id; int x, y; } touches[32]; static int touchesCount; static void Window_AddTouch(long id, int x, int y) { - touches[touchesCount].id = id; - touches[touchesCount].x = x; - touches[touchesCount].y = y; + int i = touchesCount; + touches[i].id = id; + touches[i].x = x; + touches[i].y = y; touchesCount++; - Mouse_SetPosition(x, y); - Input_SetPressed(KEY_LMOUSE, true); + Pointer_SetPosition(i, x, y); + /* TODO: redo this */ + if (i == 0) { + Input_SetPressed(KEY_LMOUSE, true); + } else { + Pointer_SetPressed(i, true); + } } static void Window_UpdateTouch(long id, int x, int y) { @@ -116,7 +122,7 @@ static void Window_UpdateTouch(long id, int x, int y) { if (win_rawMouse) { Event_RaiseMove(&PointerEvents.RawMoved, i, x - touches[i].x, y - touches[i].y); } - Mouse_SetPosition(x, y); + Pointer_SetPosition(i, x, y); touches[i].x = x; touches[i].y = y; @@ -135,8 +141,14 @@ static void Window_RemoveTouch(long id, int x, int y) { } touchesCount--; - Mouse_SetPosition(x, y); - Input_SetPressed(KEY_LMOUSE, false); + Pointer_SetPosition(i, x, y); + + /* TODO: redo this */ + if (i == 0) { + Input_SetPressed(KEY_LMOUSE, false); + } else { + Pointer_SetPressed(i, false); + } return; } } @@ -270,7 +282,7 @@ static LRESULT CALLBACK Window_Procedure(HWND handle, UINT message, WPARAM wPara Input_SetPressed(KEY_RMOUSE, (wParam & 0x02) != 0); Input_SetPressed(KEY_MMOUSE, (wParam & 0x10) != 0); /* TODO: do we need to set XBUTTON1/XBUTTON2 here */ - Mouse_SetPosition(LOWORD(lParam), HIWORD(lParam)); + Pointer_SetPosition(0, LOWORD(lParam), HIWORD(lParam)); break; case WM_MOUSEWHEEL: @@ -1114,7 +1126,7 @@ void Window_ProcessEvents(void) { break; case MotionNotify: - Mouse_SetPosition(e.xmotion.x, e.xmotion.y); + Pointer_SetPosition(0, e.xmotion.x, e.xmotion.y); break; case FocusIn: @@ -1674,7 +1686,7 @@ static OSStatus Window_ProcessMouseEvent(EventRef inEvent) { case kEventMouseMoved: case kEventMouseDragged: - Mouse_SetPosition(mouseX, mouseY); + Pointer_SetPosition(0, mouseX, mouseY); return eventNotHandledErr; } return eventNotHandledErr; @@ -2293,7 +2305,7 @@ void Window_ProcessEvents(void) { Mouse_SetWheel(Mouse_Wheel + e.wheel.y); break; case SDL_MOUSEMOTION: - Mouse_SetPosition(e.motion.x, e.motion.y); + Pointer_SetPosition(0, e.motion.x, e.motion.y); if (win_rawMouse) Event_RaiseMove(&PointerEvents.RawMoved, 0, e.motion.xrel, e.motion.yrel); break; case SDL_TEXTINPUT: @@ -2420,7 +2432,7 @@ static EM_BOOL Window_MouseMove(int type, const EmscriptenMouseEvent* ev, void* Input_SetPressed(KEY_RMOUSE, (ev->buttons & 0x02) != 0); Input_SetPressed(KEY_MMOUSE, (ev->buttons & 0x04) != 0); - Mouse_SetPosition(ev->canvasX, ev->canvasY); + Pointer_SetPosition(0, ev->canvasX, ev->canvasY); if (win_rawMouse) Event_RaiseMove(&PointerEvents.RawMoved, 0, ev->movementX, ev->movementY); return true; }