Merge pull request #739 from UnknownShadow200/MobileTouch

Improve mobile touch controls
This commit is contained in:
UnknownShadow200 2020-10-27 16:12:07 +11:00 committed by GitHub
commit 5a850f55d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 297 additions and 76 deletions

View File

@ -781,15 +781,18 @@ void LocalPlayer_SetInterpPosition(float t) {
static void LocalPlayer_HandleInput(float* xMoving, float* zMoving) { static void LocalPlayer_HandleInput(float* xMoving, float* zMoving) {
struct LocalPlayer* p = &LocalPlayer_Instance; struct LocalPlayer* p = &LocalPlayer_Instance;
struct HacksComp* hacks = &p->Hacks; struct HacksComp* hacks = &p->Hacks;
struct LocalPlayerInput* input;
if (Gui_GetInputGrab()) { if (Gui_GetInputGrab()) {
p->Physics.Jumping = false; hacks->Speeding = false; p->Physics.Jumping = false; hacks->Speeding = false;
hacks->FlyingUp = false; hacks->FlyingDown = false; hacks->FlyingUp = false; hacks->FlyingDown = false;
} else { } else {
if (KeyBind_IsPressed(KEYBIND_FORWARD)) *zMoving -= 0.98f; /* keyboard input, touch, joystick, etc */
if (KeyBind_IsPressed(KEYBIND_BACK)) *zMoving += 0.98f; for (input = &p->input; input; input = input->next) {
if (KeyBind_IsPressed(KEYBIND_LEFT)) *xMoving -= 0.98f; input->GetMovement(xMoving, zMoving);
if (KeyBind_IsPressed(KEYBIND_RIGHT)) *xMoving += 0.98f; }
*xMoving *= 0.98f;
*zMoving *= 0.98f;
p->Physics.Jumping = KeyBind_IsPressed(KEYBIND_JUMP); p->Physics.Jumping = KeyBind_IsPressed(KEYBIND_JUMP);
hacks->Speeding = hacks->Enabled && KeyBind_IsPressed(KEYBIND_SPEED); hacks->Speeding = hacks->Enabled && KeyBind_IsPressed(KEYBIND_SPEED);
@ -802,7 +805,7 @@ static void LocalPlayer_HandleInput(float* xMoving, float* zMoving) {
/* need a { } block because it's a macro */ /* need a { } block because it's a macro */
Vec3_Set(p->Base.Velocity, 0,0,0); Vec3_Set(p->Base.Velocity, 0,0,0);
} }
hacks->Noclip = KeyBind_IsPressed(KEYBIND_NOCLIP); HacksComp_SetNoclip(hacks, KeyBind_IsPressed(KEYBIND_NOCLIP));
} }
} }
} }
@ -870,6 +873,13 @@ static void LocalPlayer_CheckJumpVelocity(void* obj) {
} }
} }
static void LocalPlayer_GetMovement(float* xMoving, float* zMoving) {
if (KeyBind_IsPressed(KEYBIND_FORWARD)) *zMoving -= 1;
if (KeyBind_IsPressed(KEYBIND_BACK)) *zMoving += 1;
if (KeyBind_IsPressed(KEYBIND_LEFT)) *xMoving -= 1;
if (KeyBind_IsPressed(KEYBIND_RIGHT)) *xMoving += 1;
}
static const struct EntityVTABLE localPlayer_VTABLE = { static const struct EntityVTABLE localPlayer_VTABLE = {
LocalPlayer_Tick, Player_Despawn, LocalPlayer_SetLocation, Entity_GetCol, LocalPlayer_Tick, Player_Despawn, LocalPlayer_SetLocation, Entity_GetCol,
LocalPlayer_RenderModel, LocalPlayer_RenderName LocalPlayer_RenderModel, LocalPlayer_RenderName
@ -883,6 +893,7 @@ static void LocalPlayer_Init(void) {
Entity_SetSkin(&p->Base, &Game_Username); Entity_SetSkin(&p->Base, &Game_Username);
Event_Register_(&UserEvents.HackPermissionsChanged, NULL, LocalPlayer_CheckJumpVelocity); Event_Register_(&UserEvents.HackPermissionsChanged, NULL, LocalPlayer_CheckJumpVelocity);
p->input.GetMovement = LocalPlayer_GetMovement;
p->Collisions.Entity = &p->Base; p->Collisions.Entity = &p->Base;
HacksComp_Init(hacks); HacksComp_Init(hacks);
PhysicsComp_Init(&p->Physics, &p->Base); PhysicsComp_Init(&p->Physics, &p->Base);
@ -900,9 +911,9 @@ static void LocalPlayer_Init(void) {
hacks->SpeedMultiplier = Options_GetFloat(OPT_SPEED_FACTOR, 0.1f, 50.0f, 10.0f); hacks->SpeedMultiplier = Options_GetFloat(OPT_SPEED_FACTOR, 0.1f, 50.0f, 10.0f);
hacks->PushbackPlacing = Options_GetBool(OPT_PUSHBACK_PLACING, false); hacks->PushbackPlacing = Options_GetBool(OPT_PUSHBACK_PLACING, false);
hacks->NoclipSlide = Options_GetBool(OPT_NOCLIP_SLIDE, false); hacks->NoclipSlide = Options_GetBool(OPT_NOCLIP_SLIDE, false);
hacks->WOMStyleHacks = Options_GetBool(OPT_WOM_STYLE_HACKS, false); hacks->WOMStyleHacks = Options_GetBool(OPT_WOM_STYLE_HACKS, false);
hacks->FullBlockStep = Options_GetBool(OPT_FULL_BLOCK_STEP, false); hacks->FullBlockStep = Options_GetBool(OPT_FULL_BLOCK_STEP, false);
p->Physics.UserJumpVel = Options_GetFloat(OPT_JUMP_VELOCITY, 0.0f, 52.0f, 0.42f); p->Physics.UserJumpVel = Options_GetFloat(OPT_JUMP_VELOCITY, 0.0f, 52.0f, 0.42f);
p->Physics.JumpVel = p->Physics.UserJumpVel; p->Physics.JumpVel = p->Physics.UserJumpVel;
hackPermMsgs = Options_GetBool(OPT_HACK_PERM_MSGS, true); hackPermMsgs = Options_GetBool(OPT_HACK_PERM_MSGS, true);
@ -1015,7 +1026,7 @@ static cc_bool LocalPlayer_HandleSetSpawn(void) {
static cc_bool LocalPlayer_HandleFly(void) { static cc_bool LocalPlayer_HandleFly(void) {
struct LocalPlayer* p = &LocalPlayer_Instance; struct LocalPlayer* p = &LocalPlayer_Instance;
if (p->Hacks.CanFly && p->Hacks.Enabled) { if (p->Hacks.CanFly && p->Hacks.Enabled) {
p->Hacks.Flying = !p->Hacks.Flying; HacksComp_SetFlying(&p->Hacks, !p->Hacks.Flying);
return true; return true;
} else if (!p->_warnedFly) { } else if (!p->_warnedFly) {
p->_warnedFly = true; p->_warnedFly = true;
@ -1030,7 +1041,7 @@ static cc_bool LocalPlayer_HandleNoClip(void) {
if (p->Hacks.WOMStyleHacks) return true; /* don't handle this here */ if (p->Hacks.WOMStyleHacks) return true; /* don't handle this here */
if (p->Hacks.Noclip) p->Base.Velocity.Y = 0; if (p->Hacks.Noclip) p->Base.Velocity.Y = 0;
p->Hacks.Noclip = !p->Hacks.Noclip; HacksComp_SetNoclip(&p->Hacks, !p->Hacks.Noclip);
return true; return true;
} else if (!p->_warnedNoclip) { } else if (!p->_warnedNoclip) {
p->_warnedNoclip = true; p->_warnedNoclip = true;

View File

@ -183,6 +183,12 @@ struct NetPlayer {
CC_API void NetPlayer_Init(struct NetPlayer* player); CC_API void NetPlayer_Init(struct NetPlayer* player);
extern struct NetPlayer NetPlayers_List[ENTITIES_SELF_ID]; extern struct NetPlayer NetPlayers_List[ENTITIES_SELF_ID];
struct LocalPlayerInput;
struct LocalPlayerInput {
void (*GetMovement)(float* xMoving, float* zMoving);
struct LocalPlayerInput* next;
};
/* Represents the user/player's own entity. */ /* Represents the user/player's own entity. */
struct LocalPlayer { struct LocalPlayer {
struct Entity Base; struct Entity Base;
@ -194,6 +200,7 @@ struct LocalPlayer {
struct CollisionsComp Collisions; struct CollisionsComp Collisions;
struct PhysicsComp Physics; struct PhysicsComp Physics;
cc_bool _warnedRespawn, _warnedFly, _warnedNoclip, _warnedZoom; cc_bool _warnedRespawn, _warnedFly, _warnedNoclip, _warnedZoom;
struct LocalPlayerInput input;
}; };
extern struct LocalPlayer LocalPlayer_Instance; extern struct LocalPlayer LocalPlayer_Instance;

View File

@ -243,10 +243,11 @@ void HacksComp_RecheckFlags(struct HacksComp* hacks) {
void HacksComp_Update(struct HacksComp* hacks) { void HacksComp_Update(struct HacksComp* hacks) {
if (!hacks->CanFly || !hacks->Enabled) { if (!hacks->CanFly || !hacks->Enabled) {
hacks->Flying = false; hacks->FlyingDown = false; hacks->FlyingUp = false; HacksComp_SetFlying(hacks, false);
hacks->FlyingDown = false; hacks->FlyingUp = false;
} }
if (!hacks->CanNoclip || !hacks->Enabled) { if (!hacks->CanNoclip || !hacks->Enabled) {
hacks->Noclip = false; HacksComp_SetNoclip(hacks, false);
} }
if (!hacks->CanSpeed || !hacks->Enabled) { if (!hacks->CanSpeed || !hacks->Enabled) {
hacks->Speeding = false; hacks->HalfSpeeding = false; hacks->Speeding = false; hacks->HalfSpeeding = false;
@ -257,6 +258,18 @@ void HacksComp_Update(struct HacksComp* hacks) {
Event_RaiseVoid(&UserEvents.HackPermissionsChanged); Event_RaiseVoid(&UserEvents.HackPermissionsChanged);
} }
void HacksComp_SetFlying(struct HacksComp* hacks, cc_bool flying) {
if (hacks->Flying == flying) return;
hacks->Flying = flying;
Event_RaiseVoid(&UserEvents.HacksStateChanged);
}
void HacksComp_SetNoclip(struct HacksComp* hacks, cc_bool noclip) {
if (hacks->Noclip == noclip) return;
hacks->Noclip = noclip;
Event_RaiseVoid(&UserEvents.HacksStateChanged);
}
/*########################################################################################################################* /*########################################################################################################################*
*--------------------------------------------------InterpolationComponent-------------------------------------------------* *--------------------------------------------------InterpolationComponent-------------------------------------------------*

View File

@ -72,6 +72,8 @@ void HacksComp_RecheckFlags(struct HacksComp* hacks);
/* Updates state based on permissions (e.g. Flying set to false if CanFly is false) */ /* Updates state based on permissions (e.g. Flying set to false if CanFly is false) */
/* Raises UserEvents.HackPermissionsChanged */ /* Raises UserEvents.HackPermissionsChanged */
void HacksComp_Update(struct HacksComp* hacks); void HacksComp_Update(struct HacksComp* hacks);
void HacksComp_SetFlying(struct HacksComp* hacks, cc_bool flying);
void HacksComp_SetNoclip(struct HacksComp* hacks, cc_bool noclip);
/* Represents a position and orientation state */ /* Represents a position and orientation state */
struct InterpState { Vec3 Pos; float Pitch, Yaw, RotX, RotZ; }; struct InterpState { Vec3 Pos; float Pitch, Yaw, RotX, RotZ; };

View File

@ -135,6 +135,7 @@ CC_VAR extern struct _UserEventsList {
struct Event_Block BlockChanged; /* User changes a block */ struct Event_Block BlockChanged; /* User changes a block */
struct Event_Void HackPermissionsChanged; /* Hack permissions of the player changes */ struct Event_Void HackPermissionsChanged; /* Hack permissions of the player changes */
struct Event_Void HeldBlockChanged; /* Held block in hotbar changes */ struct Event_Void HeldBlockChanged; /* Held block in hotbar changes */
struct Event_Void HacksStateChanged; /* Hack states changed (e.g. stops flying) */
} UserEvents; } UserEvents;
CC_VAR extern struct _BlockEventsList { CC_VAR extern struct _BlockEventsList {

View File

@ -22,6 +22,7 @@ double Math_Exp(double x) { return exp(x); }
float Math_SinF(float x) { return (float)Math_Sin(x); } float Math_SinF(float x) { return (float)Math_Sin(x); }
float Math_CosF(float x) { return (float)Math_Cos(x); } float Math_CosF(float x) { return (float)Math_Cos(x); }
double Math_Atan2(double x, double y) { return atan2(y, x); }
int Math_Floor(float value) { int Math_Floor(float value) {
int valueI = (int)value; int valueI = (int)value;

View File

@ -32,6 +32,7 @@ CC_API double Math_Sin(double x);
CC_API double Math_Cos(double x); CC_API double Math_Cos(double x);
float Math_SinF(float x); float Math_SinF(float x);
float Math_CosF(float x); float Math_CosF(float x);
double Math_Atan2(double x, double y);
/* Computes loge(x). Can also be used to approximate logy(x). */ /* Computes loge(x). Can also be used to approximate logy(x). */
/* e.g. for log3(x), use: Math_Log(x)/log(3) */ /* e.g. for log3(x), use: Math_Log(x)/log(3) */

View File

@ -456,6 +456,8 @@ static void OnFileChanged(void* obj, struct Stream* stream, const cc_string* nam
Game_UpdateTexture(&Gui.GuiClassicTex, stream, name, NULL); Game_UpdateTexture(&Gui.GuiClassicTex, stream, name, NULL);
} else if (String_CaselessEqualsConst(name, "icons.png")) { } else if (String_CaselessEqualsConst(name, "icons.png")) {
Game_UpdateTexture(&Gui.IconsTex, stream, name, NULL); Game_UpdateTexture(&Gui.IconsTex, stream, name, NULL);
} else if (String_CaselessEqualsConst(name, "touch.png")) {
Game_UpdateTexture(&Gui.TouchTex, stream, name, NULL);
} }
} }
@ -488,6 +490,7 @@ static void OnContextLost(void* obj) {
Gfx_DeleteTexture(&Gui.GuiTex); Gfx_DeleteTexture(&Gui.GuiTex);
Gfx_DeleteTexture(&Gui.GuiClassicTex); Gfx_DeleteTexture(&Gui.GuiClassicTex);
Gfx_DeleteTexture(&Gui.IconsTex); Gfx_DeleteTexture(&Gui.IconsTex);
Gfx_DeleteTexture(&Gui.TouchTex);
} }
static void OnInit(void) { static void OnInit(void) {

View File

@ -41,7 +41,7 @@ CC_VAR extern struct _GuiData {
/* Whether FPS counter (and other info) is shown in top left. */ /* Whether FPS counter (and other info) is shown in top left. */
cc_bool ShowFPS; cc_bool ShowFPS;
float RawHotbarScale, RawChatScale, RawInventoryScale; float RawHotbarScale, RawChatScale, RawInventoryScale;
GfxResourceID GuiTex, GuiClassicTex, IconsTex; GfxResourceID GuiTex, GuiClassicTex, IconsTex, TouchTex;
} Gui; } Gui;
float Gui_Scale(float value); float Gui_Scale(float value);

View File

@ -63,7 +63,7 @@ static struct HUDScreen {
struct TextAtlas posAtlas; struct TextAtlas posAtlas;
double accumulator; double accumulator;
int frames, fps; int frames, fps;
cc_bool speed, halfSpeed, noclip, fly, canSpeed; cc_bool speed, halfSpeed, canSpeed, hacksChanged;
int lastFov; int lastFov;
struct HotbarWidget hotbar; struct HotbarWidget hotbar;
} HUDScreen_Instance; } HUDScreen_Instance;
@ -121,10 +121,10 @@ static void HUDScreen_DrawPosition(struct HUDScreen* s) {
Gfx_UpdateDynamicVb_IndexedTris(Models.Vb, vertices, count); Gfx_UpdateDynamicVb_IndexedTris(Models.Vb, vertices, count);
} }
static cc_bool HUDScreen_HacksChanged(struct HUDScreen* s) { static cc_bool HUDScreen_HasHacksChanged(struct HUDScreen* s) {
struct HacksComp* hacks = &LocalPlayer_Instance.Hacks; struct HacksComp* hacks = &LocalPlayer_Instance.Hacks;
return hacks->Speeding != s->speed || hacks->HalfSpeeding != s->halfSpeed || hacks->Flying != s->fly return hacks->Speeding != s->speed || hacks->HalfSpeeding != s->halfSpeed
|| hacks->Noclip != s->noclip || Game_Fov != s->lastFov || hacks->CanSpeed != s->canSpeed; || Game_Fov != s->lastFov || hacks->CanSpeed != s->canSpeed || s->hacksChanged;
} }
static void HUDScreen_UpdateHackState(struct HUDScreen* s) { static void HUDScreen_UpdateHackState(struct HUDScreen* s) {
@ -133,8 +133,9 @@ static void HUDScreen_UpdateHackState(struct HUDScreen* s) {
cc_bool speeding; cc_bool speeding;
hacks = &LocalPlayer_Instance.Hacks; hacks = &LocalPlayer_Instance.Hacks;
s->speed = hacks->Speeding; s->halfSpeed = hacks->HalfSpeeding; s->fly = hacks->Flying; s->speed = hacks->Speeding; s->halfSpeed = hacks->HalfSpeeding;
s->noclip = hacks->Noclip; s->lastFov = Game_Fov; s->canSpeed = hacks->CanSpeed; s->lastFov = Game_Fov; s->canSpeed = hacks->CanSpeed;
s->hacksChanged = false;
String_InitArray(status, statusBuffer); String_InitArray(status, statusBuffer);
if (Game_Fov != Game_DefaultFov) { if (Game_Fov != Game_DefaultFov) {
@ -246,11 +247,16 @@ static int HUDscreen_PointerDown(void* screen, int id, int x, int y) {
return false; return false;
} }
static void HUDScreen_HacksChanged(void* obj) {
((struct HUDScreen*)obj)->hacksChanged = true;
}
static void HUDScreen_Init(void* screen) { static void HUDScreen_Init(void* screen) {
struct HUDScreen* s = (struct HUDScreen*)screen; struct HUDScreen* s = (struct HUDScreen*)screen;
HotbarWidget_Create(&s->hotbar); HotbarWidget_Create(&s->hotbar);
TextWidget_Init(&s->line1); TextWidget_Init(&s->line1);
TextWidget_Init(&s->line2); TextWidget_Init(&s->line2);
Event_Register_(&UserEvents.HacksStateChanged, screen, HUDScreen_HacksChanged);
} }
static void HUDScreen_Render(void* screen, double delta) { static void HUDScreen_Render(void* screen, double delta) {
@ -264,7 +270,7 @@ static void HUDScreen_Render(void* screen, double delta) {
if (Game_ClassicMode) { if (Game_ClassicMode) {
Elem_Render(&s->line2, delta); Elem_Render(&s->line2, delta);
} else if (IsOnlyChatActive() && Gui.ShowFPS) { } else if (IsOnlyChatActive() && Gui.ShowFPS) {
if (HUDScreen_HacksChanged(s)) { HUDScreen_UpdateHackState(s); } if (HUDScreen_HasHacksChanged(s)) HUDScreen_UpdateHackState(s);
HUDScreen_DrawPosition(s); HUDScreen_DrawPosition(s);
Elem_Render(&s->line2, delta); Elem_Render(&s->line2, delta);
} }
@ -273,8 +279,12 @@ static void HUDScreen_Render(void* screen, double delta) {
Gfx_SetTexturing(false); Gfx_SetTexturing(false);
} }
static void HUDScreen_Free(void* screen) {
Event_Unregister_(&UserEvents.HacksStateChanged, screen, HUDScreen_HacksChanged);
}
static const struct ScreenVTABLE HUDScreen_VTABLE = { static const struct ScreenVTABLE HUDScreen_VTABLE = {
HUDScreen_Init, HUDScreen_Update, Screen_NullFunc, HUDScreen_Init, HUDScreen_Update, HUDScreen_Free,
HUDScreen_Render, HUDScreen_BuildMesh, HUDScreen_Render, HUDScreen_BuildMesh,
HUDScreen_KeyDown, HUDScreen_KeyUp, Screen_FKeyPress, Screen_FText, HUDScreen_KeyDown, HUDScreen_KeyUp, Screen_FKeyPress, Screen_FText,
HUDscreen_PointerDown, Screen_FPointer, Screen_FPointer, Screen_FMouseScroll, HUDscreen_PointerDown, Screen_FPointer, Screen_FPointer, Screen_FMouseScroll,
@ -1876,35 +1886,78 @@ void DisconnectScreen_Show(const cc_string* title, const cc_string* message) {
*--------------------------------------------------------TouchScreen------------------------------------------------------* *--------------------------------------------------------TouchScreen------------------------------------------------------*
*#########################################################################################################################*/ *#########################################################################################################################*/
#ifdef CC_BUILD_TOUCH #ifdef CC_BUILD_TOUCH
static struct TouchScreen { #define TOUCH_MAX_BTNS 4
Screen_Body struct TouchBindDesc {
cc_uint8 binds[7];
struct FontDesc font;
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; const char* text;
cc_uint8 bind, width; cc_uint8 bind, width;
cc_int16 x, y; cc_int16 x, y;
} touchDescs[7] = { Widget_LeftClick OnClick;
{ "<", KEYBIND_LEFT, 40, 10, 50 },
{ ">", KEYBIND_RIGHT, 40, 150, 50 },
{ "^", KEYBIND_FORWARD, 40, 80, 90 },
{ "\\/", KEYBIND_BACK, 40, 80, 10 },
{ "Jump", KEYBIND_JUMP, 100, 50, 90 },
{ "", KEYBIND_COUNT, 100, 50, 50 },
{ "More", KEYBIND_COUNT, 100, 50, 10 },
}; };
static struct TouchScreen {
Screen_Body
const struct TouchBindDesc* descs;
int numDescs;
struct FontDesc font;
struct ThumbstickWidget thumbstick;
struct ButtonWidget btns[TOUCH_MAX_BTNS];
} TouchScreen;
static struct Widget* touch_widgets[1 + TOUCH_MAX_BTNS] = {
(struct Widget*)&TouchScreen.thumbstick, (struct Widget*)&TouchScreen.btns[0],
(struct Widget*)&TouchScreen.btns[1], (struct Widget*)&TouchScreen.btns[2],
(struct Widget*)&TouchScreen.btns[3]
};
#define TOUCH_MAX_VERTICES (THUMBSTICKWIDGET_MAX + TOUCH_MAX_BTNS * BUTTONWIDGET_MAX)
static void TouchScreen_UpdateModeText(void* screen);
static void TouchScreen_ModeClick(void* s, void* w) {
Input_Placing = !Input_Placing;
TouchScreen_UpdateModeText(s);
}
static void TouchScreen_MoreClick(void* s, void* w) { TouchMoreScreen_Show(); }
static const struct TouchBindDesc normDescs[3] = {
{ "Jump", KEYBIND_JUMP, 100, 50, 90, NULL },
{ "", KEYBIND_COUNT, 100, 50, 50, TouchScreen_ModeClick },
{ "More", KEYBIND_COUNT, 100, 50, 10, TouchScreen_MoreClick },
};
static const struct TouchBindDesc hackDescs[4] = {
{ "Up", KEYBIND_FLY_UP, 100, 50, 130, NULL },
{ "Down", KEYBIND_FLY_DOWN, 100, 50, 90, NULL },
{ "", KEYBIND_COUNT, 100, 50, 50, TouchScreen_ModeClick },
{ "More", KEYBIND_COUNT, 100, 50, 10, TouchScreen_MoreClick },
};
static void TouchScreen_InitButtons(struct TouchScreen* s) {
struct HacksComp* hacks = &LocalPlayer_Instance.Hacks;
const struct TouchBindDesc* desc;
int i;
if (hacks->Flying || hacks->Noclip) {
s->descs = hackDescs;
s->numDescs = Array_Elems(hackDescs);
} else {
s->descs = normDescs;
s->numDescs = Array_Elems(normDescs);
}
s->numWidgets = 1 + s->numDescs;
for (i = 0; i < s->numDescs; i++) {
desc = &s->descs[i];
ButtonWidget_Init(&s->btns[i], desc->width, desc->OnClick);
}
}
static void TouchScreen_HacksChanged(void* screen) {
struct TouchScreen* s = (struct TouchScreen*)screen;
/* InitButtons changes number of widgets, hence */
/* must destroy graphics resources BEFORE that */
Screen_ContextLost(s);
TouchScreen_InitButtons(s);
Gui_Refresh((struct Screen*)s);
}
static void TouchScreen_ContextLost(void* screen) { static void TouchScreen_ContextLost(void* screen) {
struct TouchScreen* s = (struct TouchScreen*)screen; struct TouchScreen* s = (struct TouchScreen*)screen;
Font_Free(&s->font); Font_Free(&s->font);
@ -1913,15 +1966,10 @@ static void TouchScreen_ContextLost(void* screen) {
static void TouchScreen_UpdateModeText(void* screen) { static void TouchScreen_UpdateModeText(void* screen) {
struct TouchScreen* s = (struct TouchScreen*)screen; struct TouchScreen* s = (struct TouchScreen*)screen;
ButtonWidget_SetConst(&s->btns[5], Input_Placing ? "Place" : "Delete", &s->font); ButtonWidget_SetConst(&s->btns[s->numDescs - 2],
Input_Placing ? "Place" : "Delete", &s->font);
} }
static void TouchScreen_ModeClick(void* s, void* w) {
Input_Placing = !Input_Placing;
TouchScreen_UpdateModeText(s);
}
static void TouchScreen_MoreClick(void* s, void* w) { TouchMoreScreen_Show(); }
static void TouchScreen_ContextRecreated(void* screen) { static void TouchScreen_ContextRecreated(void* screen) {
struct TouchScreen* s = (struct TouchScreen*)screen; struct TouchScreen* s = (struct TouchScreen*)screen;
const struct TouchBindDesc* desc; const struct TouchBindDesc* desc;
@ -1929,8 +1977,8 @@ static void TouchScreen_ContextRecreated(void* screen) {
Screen_CreateVb(screen); Screen_CreateVb(screen);
Drawer2D_MakeFont(&s->font, 16, FONT_FLAGS_BOLD); Drawer2D_MakeFont(&s->font, 16, FONT_FLAGS_BOLD);
for (i = 0; i < s->numWidgets; i++) { for (i = 0; i < s->numDescs; i++) {
desc = &touchDescs[i]; desc = &s->descs[i];
ButtonWidget_SetConst(&s->btns[i], desc->text, &s->font); ButtonWidget_SetConst(&s->btns[i], desc->text, &s->font);
} }
TouchScreen_UpdateModeText(s); TouchScreen_UpdateModeText(s);
@ -1951,11 +1999,15 @@ static int TouchScreen_PointerDown(void* screen, int id, int x, int y) {
//Chat_Add1("POINTER DOWN: %i", &id); //Chat_Add1("POINTER DOWN: %i", &id);
if (Gui_GetInputGrab()) return false; if (Gui_GetInputGrab()) return false;
for (i = 0; i < s->numWidgets; i++) { if (Widget_Contains(&s->thumbstick, x, y)) {
s->thumbstick.active |= id; return true;
}
for (i = 0; i < s->numDescs; i++) {
if (!Widget_Contains(&s->btns[i], x, y)) continue; if (!Widget_Contains(&s->btns[i], x, y)) continue;
if (s->binds[i] < KEYBIND_COUNT) { if (s->descs[i].bind < KEYBIND_COUNT) {
Input_SetPressed(KeyBinds[s->binds[i]], true); Input_SetPressed(KeyBinds[s->descs[i].bind], true);
} else { } else {
s->btns[i].MenuClick(screen, &s->btns[i]); s->btns[i].MenuClick(screen, &s->btns[i]);
} }
@ -1969,12 +2021,13 @@ static int TouchScreen_PointerUp(void* screen, int id, int x, int y) {
struct TouchScreen* s = (struct TouchScreen*)screen; struct TouchScreen* s = (struct TouchScreen*)screen;
int i; int i;
//Chat_Add1("POINTER UP: %i", &id); //Chat_Add1("POINTER UP: %i", &id);
s->thumbstick.active &= ~id;
for (i = 0; i < s->numWidgets; i++) { for (i = 0; i < s->numDescs; i++) {
if (!(s->btns[i].active & id)) continue; if (!(s->btns[i].active & id)) continue;
if (s->binds[i] < KEYBIND_COUNT) { if (s->descs[i].bind < KEYBIND_COUNT) {
Input_SetPressed(KeyBinds[s->binds[i]], false); Input_SetPressed(KeyBinds[s->descs[i].bind], false);
} }
s->btns[i].active &= ~id; s->btns[i].active &= ~id;
return true; return true;
@ -1982,41 +2035,48 @@ static int TouchScreen_PointerUp(void* screen, int id, int x, int y) {
return false; return false;
} }
static void TouchScreen_GetMovement(float* xMoving, float* zMoving) {
ThumbstickWidget_GetMovement(&TouchScreen.thumbstick, xMoving, zMoving);
}
struct LocalPlayerInput touchInput;
static void TouchScreen_Init(void* screen) { static void TouchScreen_Init(void* screen) {
struct TouchScreen* s = (struct TouchScreen*)screen; struct TouchScreen* s = (struct TouchScreen*)screen;
int i;
s->widgets = touch_widgets; s->widgets = touch_widgets;
s->numWidgets = Array_Elems(touch_widgets);
s->maxVertices = TOUCH_MAX_VERTICES; s->maxVertices = TOUCH_MAX_VERTICES;
Event_Register_(&UserEvents.HacksStateChanged, screen, TouchScreen_HacksChanged);
for (i = 0; i < s->numWidgets; i++) { TouchScreen_InitButtons(s);
ButtonWidget_Init(&s->btns[i], touchDescs[i].width, NULL); ThumbstickWidget_Init(&s->thumbstick);
s->binds[i] = touchDescs[i].bind; touchInput.GetMovement = TouchScreen_GetMovement;
} LocalPlayer_Instance.input.next = &touchInput;
s->btns[5].MenuClick = TouchScreen_ModeClick;
s->btns[6].MenuClick = TouchScreen_MoreClick;
} }
static void TouchScreen_Layout(void* screen) { static void TouchScreen_Layout(void* screen) {
struct TouchScreen* s; struct TouchScreen* s = (struct TouchScreen*)screen;
const struct TouchBindDesc* desc;
int i, height; int i, height;
s = (struct TouchScreen*)screen;
HUDScreen_Layout(Gui_HUD); HUDScreen_Layout(Gui_HUD);
height = Gui_HUD->hotbar.height; height = Gui_HUD->hotbar.height;
for (i = 0; i < s->numWidgets; i++) { for (i = 0; i < s->numDescs; i++) {
Widget_SetLocation(&s->btns[i], i < 4 ? ANCHOR_MIN : ANCHOR_MAX, desc = &s->descs[i];
ANCHOR_MAX, touchDescs[i].x, touchDescs[i].y); Widget_SetLocation(&s->btns[i], ANCHOR_MAX, ANCHOR_MAX, desc->x, desc->y);
s->btns[i].yOffset += height; s->btns[i].yOffset += height;
Widget_Layout(&s->btns[i]); Widget_Layout(&s->btns[i]);
} }
Widget_SetLocation(&s->thumbstick, ANCHOR_MIN, ANCHOR_MAX, 30, 50);
}
static void TouchScreen_Free(void* s) {
Event_Unregister_(&UserEvents.HacksStateChanged, s, TouchScreen_HacksChanged);
} }
static const struct ScreenVTABLE TouchScreen_VTABLE = { static const struct ScreenVTABLE TouchScreen_VTABLE = {
TouchScreen_Init, Screen_NullUpdate, Screen_NullFunc, TouchScreen_Init, Screen_NullUpdate, TouchScreen_Free,
TouchScreen_Render, Screen_BuildMesh, TouchScreen_Render, Screen_BuildMesh,
Screen_FInput, Screen_FInput, Screen_FKeyPress, Screen_FText, Screen_FInput, Screen_FInput, Screen_FKeyPress, Screen_FText,
TouchScreen_PointerDown, TouchScreen_PointerUp, Screen_FPointer, Screen_FMouseScroll, TouchScreen_PointerDown, TouchScreen_PointerUp, Screen_FPointer, Screen_FMouseScroll,

View File

@ -2500,3 +2500,116 @@ void SpecialInputWidget_Create(struct SpecialInputWidget* w, struct FontDesc* fo
w->target = target; w->target = target;
SpecialInputWidget_InitTabs(w); SpecialInputWidget_InitTabs(w);
} }
/*########################################################################################################################*
*----------------------------------------------------ThumbstickWidget-----------------------------------------------------*
*#########################################################################################################################*/
#ifdef CC_BUILD_TOUCH
#define DIR_YMAX (1 << 0)
#define DIR_YMIN (1 << 1)
#define DIR_XMAX (1 << 2)
#define DIR_XMIN (1 << 3)
static void ThumbstickWidget_Rotate(void* widget, struct VertexTextured** vertices, int offset) {
struct ThumbstickWidget* w = (struct ThumbstickWidget*)widget;
struct VertexTextured* ptr;
int i, x, y;
ptr = *vertices - 4;
for (i = 0; i < 4; i++) {
int x = ptr[i].X - w->x;
int y = ptr[i].Y - w->y;
ptr[i].X = -y + w->x + offset;
ptr[i].Y = x + w->y;
}
}
static void ThumbstickWidget_BuildGroup(void* widget, struct Texture* tex, struct VertexTextured** vertices) {
struct ThumbstickWidget* w = (struct ThumbstickWidget*)widget;
float tmp;
tex->Y = w->y + w->height / 2;
Gfx_Make2DQuad(tex, PACKEDCOL_WHITE, vertices);
tex->Y = w->y;
tmp = tex->uv.V1; tex->uv.V1 = tex->uv.V2; tex->uv.V2 = tmp;
Gfx_Make2DQuad(tex, PACKEDCOL_WHITE, vertices);
/* TODO: The two X sides */
Gfx_Make2DQuad(tex, PACKEDCOL_WHITE, vertices);
ThumbstickWidget_Rotate(widget, vertices, w->width);
tmp = tex->uv.V1; tex->uv.V1 = tex->uv.V2; tex->uv.V2 = tmp;
Gfx_Make2DQuad(tex, PACKEDCOL_WHITE, vertices);
ThumbstickWidget_Rotate(widget, vertices, w->width / 2);
}
static void ThumbstickWidget_BuildMesh(void* widget, struct VertexTextured** vertices) {
struct ThumbstickWidget* w = (struct ThumbstickWidget*)widget;
struct Texture tex;
tex.X = w->x;
tex.Width = w->width; tex.Height = w->height / 2;
tex.uv.U1 = 0.0f; tex.uv.U2 = 1.0f;
tex.uv.V1 = 0.0f; tex.uv.V2 = 0.5f;
ThumbstickWidget_BuildGroup(widget, &tex, vertices);
tex.uv.V1 = 0.5f; tex.uv.V2 = 1.0f;
ThumbstickWidget_BuildGroup(widget, &tex, vertices);
}
static int ThumbstickWidget_CalcDirs(struct ThumbstickWidget* w) {
int i, dx, dy, dirs = 0;
double angle;
for (i = 0; i < INPUT_MAX_POINTERS; i++) {
if (!(w->active & (1 << i))) continue;
dx = Pointers[i].x - (w->x + w->width / 2);
dy = Pointers[i].y - (w->y + w->height / 2);
angle = Math_Atan2(dx, dy) * MATH_RAD2DEG;
/* 4 quadrants diagonally, but slightly expanded for overlap*/
if (angle >= 30 && angle <= 150) dirs |= DIR_YMAX;
if (angle >= -60 && angle <= 60) dirs |= DIR_XMAX;
if (angle >= -150 && angle <= -30) dirs |= DIR_YMIN;
if (angle < -120 || angle > 120) dirs |= DIR_XMIN;
}
return dirs;
}
static int ThumbstickWidget_Render2(void* widget, int offset) {
struct ThumbstickWidget* w = (struct ThumbstickWidget*)widget;
int i, base, flags = ThumbstickWidget_CalcDirs(w);
if (Gui.TouchTex) {
Gfx_BindTexture(Gui.TouchTex);
for (i = 0; i < 4; i++) {
base = (flags & (1 << i)) ? 0 : THUMBSTICKWIDGET_PER;
Gfx_DrawVb_IndexedTris_Range(4, offset + base + (i * 4));
}
}
return offset + THUMBSTICKWIDGET_MAX;
}
static const struct WidgetVTABLE ThumbstickWidget_VTABLE = {
NULL, Screen_NullFunc, Widget_CalcPosition,
Widget_Key, Widget_Key, Widget_MouseScroll,
Widget_Pointer, Widget_Pointer, Widget_PointerMove,
ThumbstickWidget_BuildMesh, ThumbstickWidget_Render2
};
void ThumbstickWidget_Init(struct ThumbstickWidget* w) {
Widget_Reset(w);
w->VTABLE = &ThumbstickWidget_VTABLE;
w->width = Display_ScaleX(128);
w->height = Display_ScaleY(128);
}
void ThumbstickWidget_GetMovement(struct ThumbstickWidget* w, float* xMoving, float* zMoving) {
int dirs = ThumbstickWidget_CalcDirs(w);
if (dirs & DIR_XMIN) *xMoving -= 1;
if (dirs & DIR_XMAX) *xMoving += 1;
if (dirs & DIR_YMIN) *zMoving -= 1;
if (dirs & DIR_YMAX) *zMoving += 1;
}
#endif

View File

@ -281,4 +281,13 @@ CC_NOINLINE void SpecialInputWidget_Create(struct SpecialInputWidget* w, struct
CC_NOINLINE void SpecialInputWidget_Redraw(struct SpecialInputWidget* w); CC_NOINLINE void SpecialInputWidget_Redraw(struct SpecialInputWidget* w);
CC_NOINLINE void SpecialInputWidget_UpdateCols(struct SpecialInputWidget* w); CC_NOINLINE void SpecialInputWidget_UpdateCols(struct SpecialInputWidget* w);
CC_NOINLINE void SpecialInputWidget_SetActive(struct SpecialInputWidget* w, cc_bool active); CC_NOINLINE void SpecialInputWidget_SetActive(struct SpecialInputWidget* w, cc_bool active);
#ifdef CC_BUILD_TOUCH
struct ThumbstickWidget { Widget_Body };
#define THUMBSTICKWIDGET_PER (4 * 4)
#define THUMBSTICKWIDGET_MAX (THUMBSTICKWIDGET_PER * 2)
void ThumbstickWidget_Init(struct ThumbstickWidget* w);
void ThumbstickWidget_GetMovement(struct ThumbstickWidget* w, float* xMoving, float* zMoving);
#endif
#endif #endif