mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-13 01:26:50 -04:00
Merge pull request #739 from UnknownShadow200/MobileTouch
Improve mobile touch controls
This commit is contained in:
commit
5a850f55d0
33
src/Entity.c
33
src/Entity.c
@ -781,15 +781,18 @@ void LocalPlayer_SetInterpPosition(float t) {
|
||||
static void LocalPlayer_HandleInput(float* xMoving, float* zMoving) {
|
||||
struct LocalPlayer* p = &LocalPlayer_Instance;
|
||||
struct HacksComp* hacks = &p->Hacks;
|
||||
struct LocalPlayerInput* input;
|
||||
|
||||
if (Gui_GetInputGrab()) {
|
||||
p->Physics.Jumping = false; hacks->Speeding = false;
|
||||
p->Physics.Jumping = false; hacks->Speeding = false;
|
||||
hacks->FlyingUp = false; hacks->FlyingDown = false;
|
||||
} else {
|
||||
if (KeyBind_IsPressed(KEYBIND_FORWARD)) *zMoving -= 0.98f;
|
||||
if (KeyBind_IsPressed(KEYBIND_BACK)) *zMoving += 0.98f;
|
||||
if (KeyBind_IsPressed(KEYBIND_LEFT)) *xMoving -= 0.98f;
|
||||
if (KeyBind_IsPressed(KEYBIND_RIGHT)) *xMoving += 0.98f;
|
||||
/* keyboard input, touch, joystick, etc */
|
||||
for (input = &p->input; input; input = input->next) {
|
||||
input->GetMovement(xMoving, zMoving);
|
||||
}
|
||||
*xMoving *= 0.98f;
|
||||
*zMoving *= 0.98f;
|
||||
|
||||
p->Physics.Jumping = KeyBind_IsPressed(KEYBIND_JUMP);
|
||||
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 */
|
||||
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 = {
|
||||
LocalPlayer_Tick, Player_Despawn, LocalPlayer_SetLocation, Entity_GetCol,
|
||||
LocalPlayer_RenderModel, LocalPlayer_RenderName
|
||||
@ -883,6 +893,7 @@ static void LocalPlayer_Init(void) {
|
||||
Entity_SetSkin(&p->Base, &Game_Username);
|
||||
Event_Register_(&UserEvents.HackPermissionsChanged, NULL, LocalPlayer_CheckJumpVelocity);
|
||||
|
||||
p->input.GetMovement = LocalPlayer_GetMovement;
|
||||
p->Collisions.Entity = &p->Base;
|
||||
HacksComp_Init(hacks);
|
||||
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->PushbackPlacing = Options_GetBool(OPT_PUSHBACK_PLACING, false);
|
||||
hacks->NoclipSlide = Options_GetBool(OPT_NOCLIP_SLIDE, false);
|
||||
hacks->WOMStyleHacks = Options_GetBool(OPT_WOM_STYLE_HACKS, false);
|
||||
hacks->FullBlockStep = Options_GetBool(OPT_FULL_BLOCK_STEP, false);
|
||||
hacks->NoclipSlide = Options_GetBool(OPT_NOCLIP_SLIDE, false);
|
||||
hacks->WOMStyleHacks = Options_GetBool(OPT_WOM_STYLE_HACKS, 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.JumpVel = p->Physics.UserJumpVel;
|
||||
hackPermMsgs = Options_GetBool(OPT_HACK_PERM_MSGS, true);
|
||||
@ -1015,7 +1026,7 @@ static cc_bool LocalPlayer_HandleSetSpawn(void) {
|
||||
static cc_bool LocalPlayer_HandleFly(void) {
|
||||
struct LocalPlayer* p = &LocalPlayer_Instance;
|
||||
if (p->Hacks.CanFly && p->Hacks.Enabled) {
|
||||
p->Hacks.Flying = !p->Hacks.Flying;
|
||||
HacksComp_SetFlying(&p->Hacks, !p->Hacks.Flying);
|
||||
return true;
|
||||
} else if (!p->_warnedFly) {
|
||||
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.Noclip) p->Base.Velocity.Y = 0;
|
||||
|
||||
p->Hacks.Noclip = !p->Hacks.Noclip;
|
||||
HacksComp_SetNoclip(&p->Hacks, !p->Hacks.Noclip);
|
||||
return true;
|
||||
} else if (!p->_warnedNoclip) {
|
||||
p->_warnedNoclip = true;
|
||||
|
@ -183,6 +183,12 @@ struct NetPlayer {
|
||||
CC_API void NetPlayer_Init(struct NetPlayer* player);
|
||||
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. */
|
||||
struct LocalPlayer {
|
||||
struct Entity Base;
|
||||
@ -194,6 +200,7 @@ struct LocalPlayer {
|
||||
struct CollisionsComp Collisions;
|
||||
struct PhysicsComp Physics;
|
||||
cc_bool _warnedRespawn, _warnedFly, _warnedNoclip, _warnedZoom;
|
||||
struct LocalPlayerInput input;
|
||||
};
|
||||
|
||||
extern struct LocalPlayer LocalPlayer_Instance;
|
||||
|
@ -243,10 +243,11 @@ void HacksComp_RecheckFlags(struct HacksComp* hacks) {
|
||||
|
||||
void HacksComp_Update(struct HacksComp* hacks) {
|
||||
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) {
|
||||
hacks->Noclip = false;
|
||||
HacksComp_SetNoclip(hacks, false);
|
||||
}
|
||||
if (!hacks->CanSpeed || !hacks->Enabled) {
|
||||
hacks->Speeding = false; hacks->HalfSpeeding = false;
|
||||
@ -257,6 +258,18 @@ void HacksComp_Update(struct HacksComp* hacks) {
|
||||
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-------------------------------------------------*
|
||||
|
@ -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) */
|
||||
/* Raises UserEvents.HackPermissionsChanged */
|
||||
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 */
|
||||
struct InterpState { Vec3 Pos; float Pitch, Yaw, RotX, RotZ; };
|
||||
|
@ -135,6 +135,7 @@ CC_VAR extern struct _UserEventsList {
|
||||
struct Event_Block BlockChanged; /* User changes a block */
|
||||
struct Event_Void HackPermissionsChanged; /* Hack permissions of the player changes */
|
||||
struct Event_Void HeldBlockChanged; /* Held block in hotbar changes */
|
||||
struct Event_Void HacksStateChanged; /* Hack states changed (e.g. stops flying) */
|
||||
} UserEvents;
|
||||
|
||||
CC_VAR extern struct _BlockEventsList {
|
||||
|
@ -22,6 +22,7 @@ double Math_Exp(double x) { return exp(x); }
|
||||
|
||||
float Math_SinF(float x) { return (float)Math_Sin(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 valueI = (int)value;
|
||||
|
@ -32,6 +32,7 @@ CC_API double Math_Sin(double x);
|
||||
CC_API double Math_Cos(double x);
|
||||
float Math_SinF(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). */
|
||||
/* e.g. for log3(x), use: Math_Log(x)/log(3) */
|
||||
|
@ -456,6 +456,8 @@ static void OnFileChanged(void* obj, struct Stream* stream, const cc_string* nam
|
||||
Game_UpdateTexture(&Gui.GuiClassicTex, stream, name, NULL);
|
||||
} else if (String_CaselessEqualsConst(name, "icons.png")) {
|
||||
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.GuiClassicTex);
|
||||
Gfx_DeleteTexture(&Gui.IconsTex);
|
||||
Gfx_DeleteTexture(&Gui.TouchTex);
|
||||
}
|
||||
|
||||
static void OnInit(void) {
|
||||
|
@ -41,7 +41,7 @@ CC_VAR extern struct _GuiData {
|
||||
/* Whether FPS counter (and other info) is shown in top left. */
|
||||
cc_bool ShowFPS;
|
||||
float RawHotbarScale, RawChatScale, RawInventoryScale;
|
||||
GfxResourceID GuiTex, GuiClassicTex, IconsTex;
|
||||
GfxResourceID GuiTex, GuiClassicTex, IconsTex, TouchTex;
|
||||
} Gui;
|
||||
|
||||
float Gui_Scale(float value);
|
||||
|
184
src/Screens.c
184
src/Screens.c
@ -63,7 +63,7 @@ static struct HUDScreen {
|
||||
struct TextAtlas posAtlas;
|
||||
double accumulator;
|
||||
int frames, fps;
|
||||
cc_bool speed, halfSpeed, noclip, fly, canSpeed;
|
||||
cc_bool speed, halfSpeed, canSpeed, hacksChanged;
|
||||
int lastFov;
|
||||
struct HotbarWidget hotbar;
|
||||
} HUDScreen_Instance;
|
||||
@ -121,10 +121,10 @@ static void HUDScreen_DrawPosition(struct HUDScreen* s) {
|
||||
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;
|
||||
return hacks->Speeding != s->speed || hacks->HalfSpeeding != s->halfSpeed || hacks->Flying != s->fly
|
||||
|| hacks->Noclip != s->noclip || Game_Fov != s->lastFov || hacks->CanSpeed != s->canSpeed;
|
||||
return hacks->Speeding != s->speed || hacks->HalfSpeeding != s->halfSpeed
|
||||
|| Game_Fov != s->lastFov || hacks->CanSpeed != s->canSpeed || s->hacksChanged;
|
||||
}
|
||||
|
||||
static void HUDScreen_UpdateHackState(struct HUDScreen* s) {
|
||||
@ -133,8 +133,9 @@ static void HUDScreen_UpdateHackState(struct HUDScreen* s) {
|
||||
cc_bool speeding;
|
||||
|
||||
hacks = &LocalPlayer_Instance.Hacks;
|
||||
s->speed = hacks->Speeding; s->halfSpeed = hacks->HalfSpeeding; s->fly = hacks->Flying;
|
||||
s->noclip = hacks->Noclip; s->lastFov = Game_Fov; s->canSpeed = hacks->CanSpeed;
|
||||
s->speed = hacks->Speeding; s->halfSpeed = hacks->HalfSpeeding;
|
||||
s->lastFov = Game_Fov; s->canSpeed = hacks->CanSpeed;
|
||||
s->hacksChanged = false;
|
||||
|
||||
String_InitArray(status, statusBuffer);
|
||||
if (Game_Fov != Game_DefaultFov) {
|
||||
@ -246,11 +247,16 @@ static int HUDscreen_PointerDown(void* screen, int id, int x, int y) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static void HUDScreen_HacksChanged(void* obj) {
|
||||
((struct HUDScreen*)obj)->hacksChanged = true;
|
||||
}
|
||||
|
||||
static void HUDScreen_Init(void* screen) {
|
||||
struct HUDScreen* s = (struct HUDScreen*)screen;
|
||||
HotbarWidget_Create(&s->hotbar);
|
||||
TextWidget_Init(&s->line1);
|
||||
TextWidget_Init(&s->line2);
|
||||
Event_Register_(&UserEvents.HacksStateChanged, screen, HUDScreen_HacksChanged);
|
||||
}
|
||||
|
||||
static void HUDScreen_Render(void* screen, double delta) {
|
||||
@ -264,7 +270,7 @@ static void HUDScreen_Render(void* screen, double delta) {
|
||||
if (Game_ClassicMode) {
|
||||
Elem_Render(&s->line2, delta);
|
||||
} else if (IsOnlyChatActive() && Gui.ShowFPS) {
|
||||
if (HUDScreen_HacksChanged(s)) { HUDScreen_UpdateHackState(s); }
|
||||
if (HUDScreen_HasHacksChanged(s)) HUDScreen_UpdateHackState(s);
|
||||
HUDScreen_DrawPosition(s);
|
||||
Elem_Render(&s->line2, delta);
|
||||
}
|
||||
@ -273,8 +279,12 @@ static void HUDScreen_Render(void* screen, double delta) {
|
||||
Gfx_SetTexturing(false);
|
||||
}
|
||||
|
||||
static void HUDScreen_Free(void* screen) {
|
||||
Event_Unregister_(&UserEvents.HacksStateChanged, screen, HUDScreen_HacksChanged);
|
||||
}
|
||||
|
||||
static const struct ScreenVTABLE HUDScreen_VTABLE = {
|
||||
HUDScreen_Init, HUDScreen_Update, Screen_NullFunc,
|
||||
HUDScreen_Init, HUDScreen_Update, HUDScreen_Free,
|
||||
HUDScreen_Render, HUDScreen_BuildMesh,
|
||||
HUDScreen_KeyDown, HUDScreen_KeyUp, Screen_FKeyPress, Screen_FText,
|
||||
HUDscreen_PointerDown, Screen_FPointer, Screen_FPointer, Screen_FMouseScroll,
|
||||
@ -1876,35 +1886,78 @@ void DisconnectScreen_Show(const cc_string* title, const cc_string* message) {
|
||||
*--------------------------------------------------------TouchScreen------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
#ifdef CC_BUILD_TOUCH
|
||||
static struct TouchScreen {
|
||||
Screen_Body
|
||||
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 {
|
||||
#define TOUCH_MAX_BTNS 4
|
||||
struct TouchBindDesc {
|
||||
const char* text;
|
||||
cc_uint8 bind, width;
|
||||
cc_int16 x, y;
|
||||
} touchDescs[7] = {
|
||||
{ "<", 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 },
|
||||
Widget_LeftClick OnClick;
|
||||
};
|
||||
|
||||
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) {
|
||||
struct TouchScreen* s = (struct TouchScreen*)screen;
|
||||
Font_Free(&s->font);
|
||||
@ -1913,15 +1966,10 @@ static void TouchScreen_ContextLost(void* screen) {
|
||||
|
||||
static void TouchScreen_UpdateModeText(void* 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) {
|
||||
struct TouchScreen* s = (struct TouchScreen*)screen;
|
||||
const struct TouchBindDesc* desc;
|
||||
@ -1929,8 +1977,8 @@ static void TouchScreen_ContextRecreated(void* screen) {
|
||||
Screen_CreateVb(screen);
|
||||
Drawer2D_MakeFont(&s->font, 16, FONT_FLAGS_BOLD);
|
||||
|
||||
for (i = 0; i < s->numWidgets; i++) {
|
||||
desc = &touchDescs[i];
|
||||
for (i = 0; i < s->numDescs; i++) {
|
||||
desc = &s->descs[i];
|
||||
ButtonWidget_SetConst(&s->btns[i], desc->text, &s->font);
|
||||
}
|
||||
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);
|
||||
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 (s->binds[i] < KEYBIND_COUNT) {
|
||||
Input_SetPressed(KeyBinds[s->binds[i]], true);
|
||||
if (s->descs[i].bind < KEYBIND_COUNT) {
|
||||
Input_SetPressed(KeyBinds[s->descs[i].bind], true);
|
||||
} else {
|
||||
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;
|
||||
int i;
|
||||
//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->binds[i] < KEYBIND_COUNT) {
|
||||
Input_SetPressed(KeyBinds[s->binds[i]], false);
|
||||
if (s->descs[i].bind < KEYBIND_COUNT) {
|
||||
Input_SetPressed(KeyBinds[s->descs[i].bind], false);
|
||||
}
|
||||
s->btns[i].active &= ~id;
|
||||
return true;
|
||||
@ -1982,41 +2035,48 @@ static int TouchScreen_PointerUp(void* screen, int id, int x, int y) {
|
||||
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) {
|
||||
struct TouchScreen* s = (struct TouchScreen*)screen;
|
||||
int i;
|
||||
|
||||
s->widgets = touch_widgets;
|
||||
s->numWidgets = Array_Elems(touch_widgets);
|
||||
s->maxVertices = TOUCH_MAX_VERTICES;
|
||||
Event_Register_(&UserEvents.HacksStateChanged, screen, TouchScreen_HacksChanged);
|
||||
|
||||
for (i = 0; i < s->numWidgets; i++) {
|
||||
ButtonWidget_Init(&s->btns[i], touchDescs[i].width, NULL);
|
||||
s->binds[i] = touchDescs[i].bind;
|
||||
}
|
||||
|
||||
s->btns[5].MenuClick = TouchScreen_ModeClick;
|
||||
s->btns[6].MenuClick = TouchScreen_MoreClick;
|
||||
TouchScreen_InitButtons(s);
|
||||
ThumbstickWidget_Init(&s->thumbstick);
|
||||
touchInput.GetMovement = TouchScreen_GetMovement;
|
||||
LocalPlayer_Instance.input.next = &touchInput;
|
||||
}
|
||||
|
||||
static void TouchScreen_Layout(void* screen) {
|
||||
struct TouchScreen* s;
|
||||
struct TouchScreen* s = (struct TouchScreen*)screen;
|
||||
const struct TouchBindDesc* desc;
|
||||
int i, height;
|
||||
|
||||
s = (struct TouchScreen*)screen;
|
||||
HUDScreen_Layout(Gui_HUD);
|
||||
height = Gui_HUD->hotbar.height;
|
||||
|
||||
for (i = 0; i < s->numWidgets; i++) {
|
||||
Widget_SetLocation(&s->btns[i], i < 4 ? ANCHOR_MIN : ANCHOR_MAX,
|
||||
ANCHOR_MAX, touchDescs[i].x, touchDescs[i].y);
|
||||
for (i = 0; i < s->numDescs; i++) {
|
||||
desc = &s->descs[i];
|
||||
Widget_SetLocation(&s->btns[i], ANCHOR_MAX, ANCHOR_MAX, desc->x, desc->y);
|
||||
s->btns[i].yOffset += height;
|
||||
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 = {
|
||||
TouchScreen_Init, Screen_NullUpdate, Screen_NullFunc,
|
||||
TouchScreen_Init, Screen_NullUpdate, TouchScreen_Free,
|
||||
TouchScreen_Render, Screen_BuildMesh,
|
||||
Screen_FInput, Screen_FInput, Screen_FKeyPress, Screen_FText,
|
||||
TouchScreen_PointerDown, TouchScreen_PointerUp, Screen_FPointer, Screen_FMouseScroll,
|
||||
|
113
src/Widgets.c
113
src/Widgets.c
@ -2500,3 +2500,116 @@ void SpecialInputWidget_Create(struct SpecialInputWidget* w, struct FontDesc* fo
|
||||
w->target = target;
|
||||
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
|
||||
|
@ -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_UpdateCols(struct SpecialInputWidget* w);
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user