From 57d9b5f2381237f312530dbdc4fb0fc5a3940933 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Tue, 3 Sep 2019 19:09:45 +1000 Subject: [PATCH] Combine input/inputhandler --- src/ClassiCube.vcxproj | 2 - src/ClassiCube.vcxproj.filters | 6 - src/Game.c | 2 +- src/Gui.c | 2 +- src/Input.c | 586 ++++++++++++++++++++++++++++++++- src/Input.h | 15 +- src/InputHandler.c | 580 -------------------------------- src/InputHandler.h | 13 - 8 files changed, 594 insertions(+), 612 deletions(-) delete mode 100644 src/InputHandler.c delete mode 100644 src/InputHandler.h diff --git a/src/ClassiCube.vcxproj b/src/ClassiCube.vcxproj index 0fb2c2115..bec8d5ea3 100644 --- a/src/ClassiCube.vcxproj +++ b/src/ClassiCube.vcxproj @@ -215,7 +215,6 @@ - @@ -272,7 +271,6 @@ - diff --git a/src/ClassiCube.vcxproj.filters b/src/ClassiCube.vcxproj.filters index 17d3d79b8..d1fb3b920 100644 --- a/src/ClassiCube.vcxproj.filters +++ b/src/ClassiCube.vcxproj.filters @@ -240,9 +240,6 @@ Header Files\Rendering - - Header Files\Game - Header Files\Math @@ -419,9 +416,6 @@ Source Files\Rendering - - Source Files\Game - Source Files\Math diff --git a/src/Game.c b/src/Game.c index 784e6d5e8..f23a6d9a2 100644 --- a/src/Game.c +++ b/src/Game.c @@ -20,7 +20,7 @@ #include "Particle.h" #include "Http.h" #include "Inventory.h" -#include "InputHandler.h" +#include "Input.h" #include "Server.h" #include "TexturePack.h" #include "Screens.h" diff --git a/src/Gui.c b/src/Gui.c index f261d19e0..511d945da 100644 --- a/src/Gui.c +++ b/src/Gui.c @@ -7,7 +7,7 @@ #include "ExtMath.h" #include "Screens.h" #include "Camera.h" -#include "InputHandler.h" +#include "Input.h" #include "Logger.h" #include "Platform.h" #include "Bitmap.h" diff --git a/src/Input.c b/src/Input.c index c347c9185..605cba7e3 100644 --- a/src/Input.c +++ b/src/Input.c @@ -6,6 +6,37 @@ #include "Logger.h" #include "Platform.h" #include "Chat.h" +#include "Utils.h" +#include "Server.h" +#include "HeldBlockRenderer.h" +#include "Game.h" +#include "Platform.h" +#include "ExtMath.h" +#include "Camera.h" +#include "Inventory.h" +#include "World.h" +#include "Event.h" +#include "Window.h" +#include "Entity.h" +#include "Chat.h" +#include "Funcs.h" +#include "Screens.h" +#include "Block.h" +#include "Menus.h" +#include "Gui.h" +#include "Protocol.h" +#include "AxisLinesRenderer.h" + +static bool input_buttonsDown[3]; +static int input_pickingId = -1; +static const short normDists[10] = { 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096 }; +static const short classicDists[4] = { 8, 32, 128, 512 }; +static TimeMS input_lastClick; +static float input_fovIndex = -1.0f; +#ifdef CC_BUILD_WEB +static bool suppressEscape; +#endif +enum MouseButton_ { MOUSE_LEFT, MOUSE_RIGHT, MOUSE_MIDDLE }; /*########################################################################################################################* @@ -247,7 +278,8 @@ void KeyBind_Set(KeyBind binding, Key key) { KeyBind_Save(); } -void KeyBind_Init(void) { +/* Initialises and loads key bindings from options */ +static void KeyBind_Init(void) { int i; for (i = 0; i < KEYBIND_COUNT; i++) { KeyBinds[i] = KeyBind_Defaults[i]; @@ -375,7 +407,8 @@ int Hotkeys_FindPartial(Key key) { return -1; } -void Hotkeys_Init(void) { +/* Initialises and loads hotkeys from options. */ +static void Hotkeys_Init(void) { static const String prefix = String_FromConst("hotkey-"); String strKey, strMods, strMore, strText; String entry, key, value; @@ -423,3 +456,552 @@ void Hotkeys_UserAddedHotkey(Key trigger, cc_uint8 modifiers, bool moreInput, co String_Format2(&value, "%t&%s", &moreInput, text); Options_SetString(&key, &value); } + + +/*########################################################################################################################* +*-----------------------------------------------------Mouse helpers-------------------------------------------------------* +*#########################################################################################################################*/ +static void MouseStateUpdate(int button, bool pressed) { + struct Entity* p; + /* defer getting the targeted entity, as it's a costly operation */ + if (input_pickingId == -1) { + p = &LocalPlayer_Instance.Base; + input_pickingId = Entities_GetCloset(p); + } + + input_buttonsDown[button] = pressed; + CPE_SendPlayerClick(button, pressed, (EntityID)input_pickingId, &Game_SelectedPos); +} + +static void MouseStateChanged(int button, bool pressed) { + if (!Server.SupportsPlayerClick) return; + + if (pressed) { + /* Can send multiple Pressed events */ + MouseStateUpdate(button, true); + } else { + if (!input_buttonsDown[button]) return; + MouseStateUpdate(button, false); + } +} + +static void MouseStatePress(int button) { + input_lastClick = DateTime_CurrentUTC_MS(); + input_pickingId = -1; + MouseStateChanged(button, true); +} + +static void MouseStateRelease(int button) { + input_pickingId = -1; + MouseStateChanged(button, false); +} + +void InputHandler_OnScreensChanged(void) { + input_lastClick = DateTime_CurrentUTC_MS(); + input_pickingId = -1; + + MouseStateChanged(MOUSE_LEFT, false); + MouseStateChanged(MOUSE_RIGHT, false); + MouseStateChanged(MOUSE_MIDDLE, false); +} + +static bool TouchesSolid(BlockID b) { return Blocks.Collide[b] == COLLIDE_SOLID; } +static bool PushbackPlace(struct AABB* blockBB) { + struct Entity* p = &LocalPlayer_Instance.Base; + struct HacksComp* hacks = &LocalPlayer_Instance.Hacks; + Face closestFace; + bool insideMap; + + Vec3 pos = p->Position; + struct AABB playerBB; + struct LocationUpdate update; + + /* Offset position by the closest face */ + closestFace = Game_SelectedPos.Closest; + if (closestFace == FACE_XMAX) { + pos.X = blockBB->Max.X + 0.5f; + } else if (closestFace == FACE_ZMAX) { + pos.Z = blockBB->Max.Z + 0.5f; + } else if (closestFace == FACE_XMIN) { + pos.X = blockBB->Min.X - 0.5f; + } else if (closestFace == FACE_ZMIN) { + pos.Z = blockBB->Min.Z - 0.5f; + } else if (closestFace == FACE_YMAX) { + pos.Y = blockBB->Min.Y + 1 + ENTITY_ADJUSTMENT; + } else if (closestFace == FACE_YMIN) { + pos.Y = blockBB->Min.Y - p->Size.Y - ENTITY_ADJUSTMENT; + } + + /* Exclude exact map boundaries, otherwise player can get stuck outside map */ + /* Being vertically above the map is acceptable though */ + insideMap = + pos.X > 0.0f && pos.Y >= 0.0f && pos.Z > 0.0f && + pos.X < World.Width && pos.Z < World.Length; + if (!insideMap) return false; + + AABB_Make(&playerBB, &pos, &p->Size); + if (!hacks->Noclip && Entity_TouchesAny(&playerBB, TouchesSolid)) { + /* Don't put player inside another block */ + return false; + } + + LocationUpdate_MakePos(&update, pos, false); + p->VTABLE->SetLocation(p, &update, false); + return true; +} + +static bool IntersectsOthers(Vec3 pos, BlockID block) { + struct AABB blockBB, entityBB; + struct Entity* entity; + int id; + + Vec3_Add(&blockBB.Min, &pos, &Blocks.MinBB[block]); + Vec3_Add(&blockBB.Max, &pos, &Blocks.MaxBB[block]); + + for (id = 0; id < ENTITIES_SELF_ID; id++) { + entity = Entities.List[id]; + if (!entity) continue; + + Entity_GetBounds(entity, &entityBB); + entityBB.Min.Y += 1.0f / 32.0f; /* when player is exactly standing on top of ground */ + if (AABB_Intersects(&entityBB, &blockBB)) return true; + } + return false; +} + +static bool CheckIsFree(BlockID block) { + struct Entity* p = &LocalPlayer_Instance.Base; + struct HacksComp* hacks = &LocalPlayer_Instance.Hacks; + + Vec3 pos, nextPos; + struct AABB blockBB, playerBB; + struct LocationUpdate update; + + /* Non solid blocks (e.g. water/flowers) can always be placed on players */ + if (Blocks.Collide[block] != COLLIDE_SOLID) return true; + + IVec3_ToVec3(&pos, &Game_SelectedPos.TranslatedPos); + if (IntersectsOthers(pos, block)) return false; + + nextPos = LocalPlayer_Instance.Interp.Next.Pos; + Vec3_Add(&blockBB.Min, &pos, &Blocks.MinBB[block]); + Vec3_Add(&blockBB.Max, &pos, &Blocks.MaxBB[block]); + + /* NOTE: Need to also test against next position here, otherwise player can */ + /* fall through the block at feet as collision is performed against nextPos */ + Entity_GetBounds(p, &playerBB); + playerBB.Min.Y = min(nextPos.Y, playerBB.Min.Y); + + if (hacks->Noclip || !AABB_Intersects(&playerBB, &blockBB)) return true; + if (hacks->CanPushbackBlocks && hacks->PushbackPlacing && hacks->Enabled) { + return PushbackPlace(&blockBB); + } + + playerBB.Min.Y += 0.25f + ENTITY_ADJUSTMENT; + if (AABB_Intersects(&playerBB, &blockBB)) return false; + + /* Push player upwards when they are jumping and trying to place a block underneath them */ + nextPos.Y = pos.Y + Blocks.MaxBB[block].Y + ENTITY_ADJUSTMENT; + LocationUpdate_MakePos(&update, nextPos, false); + p->VTABLE->SetLocation(p, &update, false); + return true; +} + +static void InputHandler_DeleteBlock(void) { + IVec3 pos; + BlockID old; + /* always play delete animations, even if we aren't deleting a block */ + HeldBlockRenderer_ClickAnim(true); + + pos = Game_SelectedPos.BlockPos; + if (!Game_SelectedPos.Valid || !World_Contains(pos.X, pos.Y, pos.Z)) return; + + old = World_GetBlock(pos.X, pos.Y, pos.Z); + if (Blocks.Draw[old] == DRAW_GAS || !Blocks.CanDelete[old]) return; + + Game_ChangeBlock(pos.X, pos.Y, pos.Z, BLOCK_AIR); + Event_RaiseBlock(&UserEvents.BlockChanged, pos, old, BLOCK_AIR); +} + +static void InputHandler_PlaceBlock(void) { + IVec3 pos; + BlockID old, block; + pos = Game_SelectedPos.TranslatedPos; + if (!Game_SelectedPos.Valid || !World_Contains(pos.X, pos.Y, pos.Z)) return; + + old = World_GetBlock(pos.X, pos.Y, pos.Z); + block = Inventory_SelectedBlock; + if (AutoRotate_Enabled) block = AutoRotate_RotateBlock(block); + + if (Game_CanPick(old) || !Blocks.CanPlace[block]) return; + /* air-ish blocks can only replace over other air-ish blocks */ + if (Blocks.Draw[block] == DRAW_GAS && Blocks.Draw[old] != DRAW_GAS) return; + if (!CheckIsFree(block)) return; + + Game_ChangeBlock(pos.X, pos.Y, pos.Z, block); + Event_RaiseBlock(&UserEvents.BlockChanged, pos, old, block); +} + +static void InputHandler_PickBlock(void) { + IVec3 pos; + BlockID cur; + pos = Game_SelectedPos.BlockPos; + if (!World_Contains(pos.X, pos.Y, pos.Z)) return; + + cur = World_GetBlock(pos.X, pos.Y, pos.Z); + if (Blocks.Draw[cur] == DRAW_GAS) return; + if (!(Blocks.CanPlace[cur] || Blocks.CanDelete[cur])) return; + Inventory_PickBlock(cur); +} + +void InputHandler_PickBlocks(void) { + bool left, middle, right; + TimeMS now = DateTime_CurrentUTC_MS(); + int delta = (int)(now - input_lastClick); + + if (delta < 250) return; /* 4 times per second */ + input_lastClick = now; + if (Gui_GetInputGrab()) return; + + left = KeyBind_IsPressed(KEYBIND_DELETE_BLOCK); + middle = KeyBind_IsPressed(KEYBIND_PICK_BLOCK); + right = KeyBind_IsPressed(KEYBIND_PLACE_BLOCK); + + if (Server.SupportsPlayerClick) { + input_pickingId = -1; + MouseStateChanged(MOUSE_LEFT, left); + MouseStateChanged(MOUSE_RIGHT, right); + MouseStateChanged(MOUSE_MIDDLE, middle); + } + + if (left) { + InputHandler_DeleteBlock(); + } else if (right) { + InputHandler_PlaceBlock(); + } else if (middle) { + InputHandler_PickBlock(); + } +} + + +/*########################################################################################################################* +*------------------------------------------------------Key helpers--------------------------------------------------------* +*#########################################################################################################################*/ +static bool InputHandler_IsShutdown(Key key) { + if (key == KEY_F4 && Key_IsAltPressed()) return true; + + /* On OSX, Cmd+Q should also terminate the process */ +#ifdef CC_BUILD_OSX + return key == 'Q' && Key_IsWinPressed(); +#else + return false; +#endif +} + +static void InputHandler_Toggle(Key key, bool* target, const char* enableMsg, const char* disableMsg) { + *target = !(*target); + if (*target) { + Chat_Add2("%c. &ePress &a%c &eto disable.", enableMsg, Input_Names[key]); + } else { + Chat_Add2("%c. &ePress &a%c &eto re-enable.", disableMsg, Input_Names[key]); + } +} + +static void InputHandler_CycleDistanceForwards(const short* viewDists, int count) { + int i, dist; + for (i = 0; i < count; i++) { + dist = viewDists[i]; + + if (dist > Game_UserViewDistance) { + Game_UserSetViewDistance(dist); return; + } + } + Game_UserSetViewDistance(viewDists[0]); +} + +static void InputHandler_CycleDistanceBackwards(const short* viewDists, int count) { + int i, dist; + for (i = count - 1; i >= 0; i--) { + dist = viewDists[i]; + + if (dist < Game_UserViewDistance) { + Game_UserSetViewDistance(dist); return; + } + } + Game_UserSetViewDistance(viewDists[count - 1]); +} + +bool InputHandler_SetFOV(int fov) { + struct HacksComp* h = &LocalPlayer_Instance.Hacks; + if (!h->Enabled || !h->CanUseThirdPersonCamera) return false; + + Game_ZoomFov = fov; + Game_SetFov(fov); + return true; +} + +static bool InputHandler_DoFovZoom(float deltaPrecise) { + struct HacksComp* h; + if (!KeyBind_IsPressed(KEYBIND_ZOOM_SCROLL)) return false; + + h = &LocalPlayer_Instance.Hacks; + if (!h->Enabled || !h->CanUseThirdPersonCamera) return false; + + if (input_fovIndex == -1.0f) input_fovIndex = (float)Game_ZoomFov; + input_fovIndex -= deltaPrecise * 5.0f; + + Math_Clamp(input_fovIndex, 1.0f, Game_DefaultFov); + return InputHandler_SetFOV((int)input_fovIndex); +} + +static void InputHandler_CheckZoomFov(void* obj) { + struct HacksComp* h = &LocalPlayer_Instance.Hacks; + if (!h->Enabled || !h->CanUseThirdPersonCamera) Game_SetFov(Game_DefaultFov); +} + +static bool HandleBlockKey(Key key) { + if (Gui_GetInputGrab()) return false; + + if (key == KeyBinds[KEYBIND_DELETE_BLOCK]) { + MouseStatePress(MOUSE_LEFT); + InputHandler_DeleteBlock(); + } else if (key == KeyBinds[KEYBIND_PLACE_BLOCK]) { + MouseStatePress(MOUSE_RIGHT); + InputHandler_PlaceBlock(); + } else if (key == KeyBinds[KEYBIND_PICK_BLOCK]) { + MouseStatePress(MOUSE_MIDDLE); + InputHandler_PickBlock(); + } else { + return false; + } + return true; +} + +static bool HandleNonClassicKey(Key key) { + if (key == KeyBinds[KEYBIND_HIDE_GUI]) { + Game_HideGui = !Game_HideGui; + } else if (key == KeyBinds[KEYBIND_SMOOTH_CAMERA]) { + InputHandler_Toggle(key, &Camera.Smooth, + " &eSmooth camera is &aenabled", + " &eSmooth camera is &cdisabled"); + } else if (key == KeyBinds[KEYBIND_AXIS_LINES]) { + InputHandler_Toggle(key, &AxisLinesRenderer_Enabled, + " &eAxis lines (&4X&e, &2Y&e, &1Z&e) now show", + " &eAxis lines no longer show"); + } else if (key == KeyBinds[KEYBIND_AUTOROTATE]) { + InputHandler_Toggle(key, &AutoRotate_Enabled, + " &eAuto rotate is &aenabled", + " &eAuto rotate is &cdisabled"); + } else if (key == KeyBinds[KEYBIND_THIRD_PERSON]) { + Camera_CycleActive(); + } else if (key == KeyBinds[KEYBIND_DROP_BLOCK]) { + if (Inventory_CheckChangeSelected() && Inventory_SelectedBlock != BLOCK_AIR) { + /* Don't assign SelectedIndex directly, because we don't want held block + switching positions if they already have air in their inventory hotbar. */ + Inventory_Set(Inventory.SelectedIndex, BLOCK_AIR); + Event_RaiseVoid(&UserEvents.HeldBlockChanged); + } + } else if (key == KeyBinds[KEYBIND_IDOVERLAY]) { + TexIdsOverlay_Show(); + } else if (key == KeyBinds[KEYBIND_BREAK_LIQUIDS]) { + InputHandler_Toggle(key, &Game_BreakableLiquids, + " &eBreakable liquids is &aenabled", + " &eBreakable liquids is &cdisabled"); + } else { + return false; + } + return true; +} + +static bool HandleCoreKey(Key key) { + if (key == KeyBinds[KEYBIND_HIDE_FPS]) { + Gui_ShowFPS = !Gui_ShowFPS; + } else if (key == KeyBinds[KEYBIND_FULLSCREEN]) { + int state = Window_GetWindowState(); + + if (state == WINDOW_STATE_FULLSCREEN) { + Window_ExitFullscreen(); + } else if (state != WINDOW_STATE_MINIMISED) { + Window_EnterFullscreen(); + } + } else if (key == KeyBinds[KEYBIND_FOG]) { + const short* viewDists = Gui_ClassicMenu ? classicDists : normDists; + int count = Gui_ClassicMenu ? Array_Elems(classicDists) : Array_Elems(normDists); + + if (Key_IsShiftPressed()) { + InputHandler_CycleDistanceBackwards(viewDists, count); + } else { + InputHandler_CycleDistanceForwards(viewDists, count); + } + } else if (key == KEY_F5 && Game_ClassicMode) { + int weather = Env.Weather == WEATHER_SUNNY ? WEATHER_RAINY : WEATHER_SUNNY; + Env_SetWeather(weather); + } else { + if (Game_ClassicMode) return false; + return HandleNonClassicKey(key); + } + return true; +} + +static void HandleHotkeyDown(Key key) { + struct HotkeyData* hkey; + String text; + int i = Hotkeys_FindPartial(key); + + if (i == -1) return; + hkey = &HotkeysList[i]; + text = StringsBuffer_UNSAFE_Get(&HotkeysText, hkey->TextIndex); + + if (!hkey->StaysOpen) { + Chat_Send(&text, false); + } else if (!Gui_GetInputGrab()) { + HUDScreen_OpenInput(&text); + } +} + + +/*########################################################################################################################* +*-----------------------------------------------------Base handlers-------------------------------------------------------* +*#########################################################################################################################*/ +static void HandleMouseWheel(void* obj, float delta) { + struct Screen* s; + int i; + struct Widget* widget; + bool hotbar; + + for (i = 0; i < Gui_ScreensCount; i++) { + s = Gui_Screens[i]; + if (s->VTABLE->HandlesMouseScroll(s, delta)) return; + } + + hotbar = Key_IsAltPressed() || Key_IsControlPressed() || Key_IsShiftPressed(); + if (!hotbar && Camera.Active->Zoom(delta)) return; + if (InputHandler_DoFovZoom(delta) || !Inventory.CanChangeSelected) return; + + widget = HUDScreen_GetHotbar(); + Elem_HandlesMouseScroll(widget, delta); +} + +static void HandlePointerMove(void* obj, int idx, int xDelta, int yDelta) { + struct Screen* s; + int i, x = Pointers[idx].x, y = Pointers[idx].y; + + for (i = 0; i < Gui_ScreensCount; i++) { + s = Gui_Screens[i]; + if (s->VTABLE->HandlesPointerMove(s, 1 << idx, x, y)) return; + } +} + +static void HandlePointerDown(void* obj, int idx) { + struct Screen* s; + int i, x = Pointers[idx].x, y = Pointers[idx].y; + + for (i = 0; i < Gui_ScreensCount; i++) { + s = Gui_Screens[i]; + if (s->VTABLE->HandlesPointerDown(s, 1 << idx, x, y)) return; + } +} + +static void HandlePointerUp(void* obj, int idx) { + struct Screen* s; + int i, x = Pointers[idx].x, y = Pointers[idx].y; + + for (i = 0; i < Gui_ScreensCount; i++) { + s = Gui_Screens[i]; + if (s->VTABLE->HandlesPointerUp(s, 1 << idx, x, y)) return; + } +} + +static void HandleInputDown(void* obj, int key, bool was) { + struct Screen* s; + int i; + +#ifndef CC_BUILD_WEB + if (key == KEY_ESCAPE && (s = Gui_GetClosable())) { + /* Don't want holding down escape to go in and out of pause menu */ + if (!was) Gui_Remove(s); + return; + } +#endif + + if (InputHandler_IsShutdown(key)) { + /* TODO: Do we need a separate exit function in Game class? */ + Window_Close(); return; + } else if (key == KeyBinds[KEYBIND_SCREENSHOT] && !was) { + Game_ScreenshotRequested = true; return; + } + + for (i = 0; i < Gui_ScreensCount; i++) { + s = Gui_Screens[i]; + if (s->VTABLE->HandlesKeyDown(s, key)) return; + } + + if ((key == KEY_ESCAPE || key == KEY_PAUSE) && !Gui_GetInputGrab()) { +#ifdef CC_BUILD_WEB + /* Can't do this in KeyUp, because pressing escape without having */ + /* explicitly disabled mouse lock means a KeyUp event isn't sent. */ + /* But switching to pause screen disables mouse lock, causing a KeyUp */ + /* event to be sent, triggering the active->closable case which immediately + /* closes the pause screen. Hence why the next KeyUp must be supressed. */ + suppressEscape = true; +#endif + PauseScreen_Show(); return; + } + + /* These should not be triggered multiple times when holding down */ + if (was) return; + if (HandleBlockKey(key)) { + } else if (HandleCoreKey(key)) { + } else if (LocalPlayer_HandlesKey(key)) { + } else { HandleHotkeyDown(key); } +} + +static void HandleInputUp(void* obj, int key) { + struct Screen* s; + int i; + + if (key == KeyBinds[KEYBIND_ZOOM_SCROLL]) Game_SetFov(Game_DefaultFov); +#ifdef CC_BUILD_WEB + /* When closing menus (which reacquires mouse focus) in key down, */ + /* this still leaves the cursor visible. But if this is instead */ + /* done in key up, the cursor disappears as expected. */ + if (key == KEY_ESCAPE && (s = Gui_GetClosable())) { + if (suppressEscape) { suppressEscape = false; return; } + Gui_Remove(s); return; + } +#endif + + for (i = 0; i < Gui_ScreensCount; i++) { + s = Gui_Screens[i]; + if (s->VTABLE->HandlesKeyUp(s, key)) return; + } + + if (Gui_GetInputGrab()) return; + if (key == KeyBinds[KEYBIND_DELETE_BLOCK]) MouseStateRelease(MOUSE_LEFT); + if (key == KeyBinds[KEYBIND_PLACE_BLOCK]) MouseStateRelease(MOUSE_RIGHT); + if (key == KeyBinds[KEYBIND_PICK_BLOCK]) MouseStateRelease(MOUSE_MIDDLE); +} + +static void HandleKeyPress(void* obj, int keyChar) { + struct Screen* s; + int i; + + for (i = 0; i < Gui_ScreensCount; i++) { + s = Gui_Screens[i]; + if (s->VTABLE->HandlesKeyPress(s, keyChar)) return; + } +} + +void InputHandler_Init(void) { + Event_RegisterMove(&PointerEvents.Moved, NULL, HandlePointerMove); + Event_RegisterInt(&PointerEvents.Down, NULL, HandlePointerDown); + Event_RegisterInt(&PointerEvents.Up, NULL, HandlePointerUp); + Event_RegisterInt(&InputEvents.Down, NULL, HandleInputDown); + Event_RegisterInt(&InputEvents.Up, NULL, HandleInputUp); + Event_RegisterInt(&InputEvents.Press, NULL, HandleKeyPress); + Event_RegisterFloat(&InputEvents.Wheel, NULL, HandleMouseWheel); + + Event_RegisterVoid(&UserEvents.HackPermissionsChanged, NULL, InputHandler_CheckZoomFov); + KeyBind_Init(); + Hotkeys_Init(); +} diff --git a/src/Input.h b/src/Input.h index 007214cf9..19c2420bd 100644 --- a/src/Input.h +++ b/src/Input.h @@ -1,8 +1,9 @@ #ifndef CC_INPUT_H #define CC_INPUT_H #include "String.h" -/* Manages the keyboard, and raises events when keys are pressed etc. - Copyright 2014-2019 ClassiCube | Licensed under BSD-3 | Based on OpenTK code +/* Manages keyboard, mouse, and touch state. + Raises events when keys are pressed etc, and implements base handlers for them. + Copyright 2014-2019 ClassiCube | Licensed under BSD-3 */ enum Key_ { @@ -127,9 +128,6 @@ extern const cc_uint8 KeyBind_Defaults[KEYBIND_COUNT]; bool KeyBind_IsPressed(KeyBind binding); /* Set the key that the given key binding is bound to. (also updates options list) */ void KeyBind_Set(KeyBind binding, Key key); -/* Initalises and loads key bindings from options. */ -void KeyBind_Init(void); - extern const cc_uint8 Hotkeys_LWJGL[256]; struct HotkeyData { @@ -153,10 +151,13 @@ bool Hotkeys_Remove(Key trigger, cc_uint8 modifiers); /* Returns the first hotkey which is bound to the given key and has its modifiers pressed. */ /* NOTE: The hotkeys list is sorted, so hotkeys with most modifiers are checked first. */ int Hotkeys_FindPartial(Key key); -/* Initalises and loads hotkeys from options. */ -void Hotkeys_Init(void); /* Called when user has removed a hotkey. (removes it from options) */ void Hotkeys_UserRemovedHotkey(Key trigger, cc_uint8 modifiers); /* Called when user has added a hotkey. (Adds it to options) */ void Hotkeys_UserAddedHotkey(Key trigger, cc_uint8 modifiers, bool moreInput, const String* text); + +bool InputHandler_SetFOV(int fov); +void InputHandler_PickBlocks(void); +void InputHandler_Init(void); +void InputHandler_OnScreensChanged(void); #endif diff --git a/src/InputHandler.c b/src/InputHandler.c deleted file mode 100644 index d0b538ead..000000000 --- a/src/InputHandler.c +++ /dev/null @@ -1,580 +0,0 @@ -#include "InputHandler.h" -#include "Utils.h" -#include "Server.h" -#include "HeldBlockRenderer.h" -#include "Game.h" -#include "Platform.h" -#include "ExtMath.h" -#include "Camera.h" -#include "Inventory.h" -#include "World.h" -#include "Event.h" -#include "Window.h" -#include "Entity.h" -#include "Chat.h" -#include "Funcs.h" -#include "Screens.h" -#include "Block.h" -#include "Menus.h" -#include "Gui.h" -#include "Protocol.h" -#include "AxisLinesRenderer.h" - -static bool input_buttonsDown[3]; -static int input_pickingId = -1; -static const short normDists[10] = { 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096 }; -static const short classicDists[4] = { 8, 32, 128, 512 }; -static TimeMS input_lastClick; -static float input_fovIndex = -1.0f; -#ifdef CC_BUILD_WEB -static bool suppressEscape; -#endif -enum MouseButton_ { MOUSE_LEFT, MOUSE_RIGHT, MOUSE_MIDDLE }; - -/*########################################################################################################################* -*-----------------------------------------------------Mouse helpers-------------------------------------------------------* -*#########################################################################################################################*/ -static void MouseStateUpdate(int button, bool pressed) { - struct Entity* p; - /* defer getting the targeted entity, as it's a costly operation */ - if (input_pickingId == -1) { - p = &LocalPlayer_Instance.Base; - input_pickingId = Entities_GetCloset(p); - } - - input_buttonsDown[button] = pressed; - CPE_SendPlayerClick(button, pressed, (EntityID)input_pickingId, &Game_SelectedPos); -} - -static void MouseStateChanged(int button, bool pressed) { - if (!Server.SupportsPlayerClick) return; - - if (pressed) { - /* Can send multiple Pressed events */ - MouseStateUpdate(button, true); - } else { - if (!input_buttonsDown[button]) return; - MouseStateUpdate(button, false); - } -} - -static void MouseStatePress(int button) { - input_lastClick = DateTime_CurrentUTC_MS(); - input_pickingId = -1; - MouseStateChanged(button, true); -} - -static void MouseStateRelease(int button) { - input_pickingId = -1; - MouseStateChanged(button, false); -} - -void InputHandler_OnScreensChanged(void) { - input_lastClick = DateTime_CurrentUTC_MS(); - input_pickingId = -1; - - MouseStateChanged(MOUSE_LEFT, false); - MouseStateChanged(MOUSE_RIGHT, false); - MouseStateChanged(MOUSE_MIDDLE, false); -} - -static bool TouchesSolid(BlockID b) { return Blocks.Collide[b] == COLLIDE_SOLID; } -static bool PushbackPlace(struct AABB* blockBB) { - struct Entity* p = &LocalPlayer_Instance.Base; - struct HacksComp* hacks = &LocalPlayer_Instance.Hacks; - Face closestFace; - bool insideMap; - - Vec3 pos = p->Position; - struct AABB playerBB; - struct LocationUpdate update; - - /* Offset position by the closest face */ - closestFace = Game_SelectedPos.Closest; - if (closestFace == FACE_XMAX) { - pos.X = blockBB->Max.X + 0.5f; - } else if (closestFace == FACE_ZMAX) { - pos.Z = blockBB->Max.Z + 0.5f; - } else if (closestFace == FACE_XMIN) { - pos.X = blockBB->Min.X - 0.5f; - } else if (closestFace == FACE_ZMIN) { - pos.Z = blockBB->Min.Z - 0.5f; - } else if (closestFace == FACE_YMAX) { - pos.Y = blockBB->Min.Y + 1 + ENTITY_ADJUSTMENT; - } else if (closestFace == FACE_YMIN) { - pos.Y = blockBB->Min.Y - p->Size.Y - ENTITY_ADJUSTMENT; - } - - /* Exclude exact map boundaries, otherwise player can get stuck outside map */ - /* Being vertically above the map is acceptable though */ - insideMap = - pos.X > 0.0f && pos.Y >= 0.0f && pos.Z > 0.0f && - pos.X < World.Width && pos.Z < World.Length; - if (!insideMap) return false; - - AABB_Make(&playerBB, &pos, &p->Size); - if (!hacks->Noclip && Entity_TouchesAny(&playerBB, TouchesSolid)) { - /* Don't put player inside another block */ - return false; - } - - LocationUpdate_MakePos(&update, pos, false); - p->VTABLE->SetLocation(p, &update, false); - return true; -} - -static bool IntersectsOthers(Vec3 pos, BlockID block) { - struct AABB blockBB, entityBB; - struct Entity* entity; - int id; - - Vec3_Add(&blockBB.Min, &pos, &Blocks.MinBB[block]); - Vec3_Add(&blockBB.Max, &pos, &Blocks.MaxBB[block]); - - for (id = 0; id < ENTITIES_SELF_ID; id++) { - entity = Entities.List[id]; - if (!entity) continue; - - Entity_GetBounds(entity, &entityBB); - entityBB.Min.Y += 1.0f / 32.0f; /* when player is exactly standing on top of ground */ - if (AABB_Intersects(&entityBB, &blockBB)) return true; - } - return false; -} - -static bool CheckIsFree(BlockID block) { - struct Entity* p = &LocalPlayer_Instance.Base; - struct HacksComp* hacks = &LocalPlayer_Instance.Hacks; - - Vec3 pos, nextPos; - struct AABB blockBB, playerBB; - struct LocationUpdate update; - - /* Non solid blocks (e.g. water/flowers) can always be placed on players */ - if (Blocks.Collide[block] != COLLIDE_SOLID) return true; - - IVec3_ToVec3(&pos, &Game_SelectedPos.TranslatedPos); - if (IntersectsOthers(pos, block)) return false; - - nextPos = LocalPlayer_Instance.Interp.Next.Pos; - Vec3_Add(&blockBB.Min, &pos, &Blocks.MinBB[block]); - Vec3_Add(&blockBB.Max, &pos, &Blocks.MaxBB[block]); - - /* NOTE: Need to also test against next position here, otherwise player can */ - /* fall through the block at feet as collision is performed against nextPos */ - Entity_GetBounds(p, &playerBB); - playerBB.Min.Y = min(nextPos.Y, playerBB.Min.Y); - - if (hacks->Noclip || !AABB_Intersects(&playerBB, &blockBB)) return true; - if (hacks->CanPushbackBlocks && hacks->PushbackPlacing && hacks->Enabled) { - return PushbackPlace(&blockBB); - } - - playerBB.Min.Y += 0.25f + ENTITY_ADJUSTMENT; - if (AABB_Intersects(&playerBB, &blockBB)) return false; - - /* Push player upwards when they are jumping and trying to place a block underneath them */ - nextPos.Y = pos.Y + Blocks.MaxBB[block].Y + ENTITY_ADJUSTMENT; - LocationUpdate_MakePos(&update, nextPos, false); - p->VTABLE->SetLocation(p, &update, false); - return true; -} - -static void InputHandler_DeleteBlock(void) { - IVec3 pos; - BlockID old; - /* always play delete animations, even if we aren't deleting a block */ - HeldBlockRenderer_ClickAnim(true); - - pos = Game_SelectedPos.BlockPos; - if (!Game_SelectedPos.Valid || !World_Contains(pos.X, pos.Y, pos.Z)) return; - - old = World_GetBlock(pos.X, pos.Y, pos.Z); - if (Blocks.Draw[old] == DRAW_GAS || !Blocks.CanDelete[old]) return; - - Game_ChangeBlock(pos.X, pos.Y, pos.Z, BLOCK_AIR); - Event_RaiseBlock(&UserEvents.BlockChanged, pos, old, BLOCK_AIR); -} - -static void InputHandler_PlaceBlock(void) { - IVec3 pos; - BlockID old, block; - pos = Game_SelectedPos.TranslatedPos; - if (!Game_SelectedPos.Valid || !World_Contains(pos.X, pos.Y, pos.Z)) return; - - old = World_GetBlock(pos.X, pos.Y, pos.Z); - block = Inventory_SelectedBlock; - if (AutoRotate_Enabled) block = AutoRotate_RotateBlock(block); - - if (Game_CanPick(old) || !Blocks.CanPlace[block]) return; - /* air-ish blocks can only replace over other air-ish blocks */ - if (Blocks.Draw[block] == DRAW_GAS && Blocks.Draw[old] != DRAW_GAS) return; - if (!CheckIsFree(block)) return; - - Game_ChangeBlock(pos.X, pos.Y, pos.Z, block); - Event_RaiseBlock(&UserEvents.BlockChanged, pos, old, block); -} - -static void InputHandler_PickBlock(void) { - IVec3 pos; - BlockID cur; - pos = Game_SelectedPos.BlockPos; - if (!World_Contains(pos.X, pos.Y, pos.Z)) return; - - cur = World_GetBlock(pos.X, pos.Y, pos.Z); - if (Blocks.Draw[cur] == DRAW_GAS) return; - if (!(Blocks.CanPlace[cur] || Blocks.CanDelete[cur])) return; - Inventory_PickBlock(cur); -} - -void InputHandler_PickBlocks(void) { - bool left, middle, right; - TimeMS now = DateTime_CurrentUTC_MS(); - int delta = (int)(now - input_lastClick); - - if (delta < 250) return; /* 4 times per second */ - input_lastClick = now; - if (Gui_GetInputGrab()) return; - - left = KeyBind_IsPressed(KEYBIND_DELETE_BLOCK); - middle = KeyBind_IsPressed(KEYBIND_PICK_BLOCK); - right = KeyBind_IsPressed(KEYBIND_PLACE_BLOCK); - - if (Server.SupportsPlayerClick) { - input_pickingId = -1; - MouseStateChanged(MOUSE_LEFT, left); - MouseStateChanged(MOUSE_RIGHT, right); - MouseStateChanged(MOUSE_MIDDLE, middle); - } - - if (left) { - InputHandler_DeleteBlock(); - } else if (right) { - InputHandler_PlaceBlock(); - } else if (middle) { - InputHandler_PickBlock(); - } -} - - -/*########################################################################################################################* -*------------------------------------------------------Key helpers--------------------------------------------------------* -*#########################################################################################################################*/ -static bool InputHandler_IsShutdown(Key key) { - if (key == KEY_F4 && Key_IsAltPressed()) return true; - - /* On OSX, Cmd+Q should also terminate the process */ -#ifdef CC_BUILD_OSX - return key == 'Q' && Key_IsWinPressed(); -#else - return false; -#endif -} - -static void InputHandler_Toggle(Key key, bool* target, const char* enableMsg, const char* disableMsg) { - *target = !(*target); - if (*target) { - Chat_Add2("%c. &ePress &a%c &eto disable.", enableMsg, Input_Names[key]); - } else { - Chat_Add2("%c. &ePress &a%c &eto re-enable.", disableMsg, Input_Names[key]); - } -} - -static void InputHandler_CycleDistanceForwards(const short* viewDists, int count) { - int i, dist; - for (i = 0; i < count; i++) { - dist = viewDists[i]; - - if (dist > Game_UserViewDistance) { - Game_UserSetViewDistance(dist); return; - } - } - Game_UserSetViewDistance(viewDists[0]); -} - -static void InputHandler_CycleDistanceBackwards(const short* viewDists, int count) { - int i, dist; - for (i = count - 1; i >= 0; i--) { - dist = viewDists[i]; - - if (dist < Game_UserViewDistance) { - Game_UserSetViewDistance(dist); return; - } - } - Game_UserSetViewDistance(viewDists[count - 1]); -} - -bool InputHandler_SetFOV(int fov) { - struct HacksComp* h = &LocalPlayer_Instance.Hacks; - if (!h->Enabled || !h->CanUseThirdPersonCamera) return false; - - Game_ZoomFov = fov; - Game_SetFov(fov); - return true; -} - -static bool InputHandler_DoFovZoom(float deltaPrecise) { - struct HacksComp* h; - if (!KeyBind_IsPressed(KEYBIND_ZOOM_SCROLL)) return false; - - h = &LocalPlayer_Instance.Hacks; - if (!h->Enabled || !h->CanUseThirdPersonCamera) return false; - - if (input_fovIndex == -1.0f) input_fovIndex = (float)Game_ZoomFov; - input_fovIndex -= deltaPrecise * 5.0f; - - Math_Clamp(input_fovIndex, 1.0f, Game_DefaultFov); - return InputHandler_SetFOV((int)input_fovIndex); -} - -static void InputHandler_CheckZoomFov(void* obj) { - struct HacksComp* h = &LocalPlayer_Instance.Hacks; - if (!h->Enabled || !h->CanUseThirdPersonCamera) Game_SetFov(Game_DefaultFov); -} - -static bool HandleBlockKey(Key key) { - if (Gui_GetInputGrab()) return false; - - if (key == KeyBinds[KEYBIND_DELETE_BLOCK]) { - MouseStatePress(MOUSE_LEFT); - InputHandler_DeleteBlock(); - } else if (key == KeyBinds[KEYBIND_PLACE_BLOCK]) { - MouseStatePress(MOUSE_RIGHT); - InputHandler_PlaceBlock(); - } else if (key == KeyBinds[KEYBIND_PICK_BLOCK]) { - MouseStatePress(MOUSE_MIDDLE); - InputHandler_PickBlock(); - } else { - return false; - } - return true; -} - -static bool HandleNonClassicKey(Key key) { - if (key == KeyBinds[KEYBIND_HIDE_GUI]) { - Game_HideGui = !Game_HideGui; - } else if (key == KeyBinds[KEYBIND_SMOOTH_CAMERA]) { - InputHandler_Toggle(key, &Camera.Smooth, - " &eSmooth camera is &aenabled", - " &eSmooth camera is &cdisabled"); - } else if (key == KeyBinds[KEYBIND_AXIS_LINES]) { - InputHandler_Toggle(key, &AxisLinesRenderer_Enabled, - " &eAxis lines (&4X&e, &2Y&e, &1Z&e) now show", - " &eAxis lines no longer show"); - } else if (key == KeyBinds[KEYBIND_AUTOROTATE]) { - InputHandler_Toggle(key, &AutoRotate_Enabled, - " &eAuto rotate is &aenabled", - " &eAuto rotate is &cdisabled"); - } else if (key == KeyBinds[KEYBIND_THIRD_PERSON]) { - Camera_CycleActive(); - } else if (key == KeyBinds[KEYBIND_DROP_BLOCK]) { - if (Inventory_CheckChangeSelected() && Inventory_SelectedBlock != BLOCK_AIR) { - /* Don't assign SelectedIndex directly, because we don't want held block - switching positions if they already have air in their inventory hotbar. */ - Inventory_Set(Inventory.SelectedIndex, BLOCK_AIR); - Event_RaiseVoid(&UserEvents.HeldBlockChanged); - } - } else if (key == KeyBinds[KEYBIND_IDOVERLAY]) { - TexIdsOverlay_Show(); - } else if (key == KeyBinds[KEYBIND_BREAK_LIQUIDS]) { - InputHandler_Toggle(key, &Game_BreakableLiquids, - " &eBreakable liquids is &aenabled", - " &eBreakable liquids is &cdisabled"); - } else { - return false; - } - return true; -} - -static bool HandleCoreKey(Key key) { - if (key == KeyBinds[KEYBIND_HIDE_FPS]) { - Gui_ShowFPS = !Gui_ShowFPS; - } else if (key == KeyBinds[KEYBIND_FULLSCREEN]) { - int state = Window_GetWindowState(); - - if (state == WINDOW_STATE_FULLSCREEN) { - Window_ExitFullscreen(); - } else if (state != WINDOW_STATE_MINIMISED) { - Window_EnterFullscreen(); - } - } else if (key == KeyBinds[KEYBIND_FOG]) { - const short* viewDists = Gui_ClassicMenu ? classicDists : normDists; - int count = Gui_ClassicMenu ? Array_Elems(classicDists) : Array_Elems(normDists); - - if (Key_IsShiftPressed()) { - InputHandler_CycleDistanceBackwards(viewDists, count); - } else { - InputHandler_CycleDistanceForwards(viewDists, count); - } - } else if (key == KEY_F5 && Game_ClassicMode) { - int weather = Env.Weather == WEATHER_SUNNY ? WEATHER_RAINY : WEATHER_SUNNY; - Env_SetWeather(weather); - } else { - if (Game_ClassicMode) return false; - return HandleNonClassicKey(key); - } - return true; -} - -static void HandleHotkeyDown(Key key) { - struct HotkeyData* hkey; - String text; - int i = Hotkeys_FindPartial(key); - - if (i == -1) return; - hkey = &HotkeysList[i]; - text = StringsBuffer_UNSAFE_Get(&HotkeysText, hkey->TextIndex); - - if (!hkey->StaysOpen) { - Chat_Send(&text, false); - } else if (!Gui_GetInputGrab()) { - HUDScreen_OpenInput(&text); - } -} - - -/*########################################################################################################################* -*-----------------------------------------------------Base handlers-------------------------------------------------------* -*#########################################################################################################################*/ -static void HandleMouseWheel(void* obj, float delta) { - struct Screen* s; - int i; - struct Widget* widget; - bool hotbar; - - for (i = 0; i < Gui_ScreensCount; i++) { - s = Gui_Screens[i]; - if (s->VTABLE->HandlesMouseScroll(s, delta)) return; - } - - hotbar = Key_IsAltPressed() || Key_IsControlPressed() || Key_IsShiftPressed(); - if (!hotbar && Camera.Active->Zoom(delta)) return; - if (InputHandler_DoFovZoom(delta) || !Inventory.CanChangeSelected) return; - - widget = HUDScreen_GetHotbar(); - Elem_HandlesMouseScroll(widget, delta); -} - -static void HandlePointerMove(void* obj, int idx, int xDelta, int yDelta) { - struct Screen* s; - int i, x = Pointers[idx].x, y = Pointers[idx].y; - - for (i = 0; i < Gui_ScreensCount; i++) { - s = Gui_Screens[i]; - if (s->VTABLE->HandlesPointerMove(s, 1 << idx, x, y)) return; - } -} - -static void HandlePointerDown(void* obj, int idx) { - struct Screen* s; - int i, x = Pointers[idx].x, y = Pointers[idx].y; - - for (i = 0; i < Gui_ScreensCount; i++) { - s = Gui_Screens[i]; - if (s->VTABLE->HandlesPointerDown(s, 1 << idx, x, y)) return; - } -} - -static void HandlePointerUp(void* obj, int idx) { - struct Screen* s; - int i, x = Pointers[idx].x, y = Pointers[idx].y; - - for (i = 0; i < Gui_ScreensCount; i++) { - s = Gui_Screens[i]; - if (s->VTABLE->HandlesPointerUp(s, 1 << idx, x, y)) return; - } -} - -static void HandleInputDown(void* obj, int key, bool was) { - struct Screen* s; - int i; - -#ifndef CC_BUILD_WEB - if (key == KEY_ESCAPE && (s = Gui_GetClosable())) { - /* Don't want holding down escape to go in and out of pause menu */ - if (!was) Gui_Remove(s); - return; - } -#endif - - if (InputHandler_IsShutdown(key)) { - /* TODO: Do we need a separate exit function in Game class? */ - Window_Close(); return; - } else if (key == KeyBinds[KEYBIND_SCREENSHOT] && !was) { - Game_ScreenshotRequested = true; return; - } - - for (i = 0; i < Gui_ScreensCount; i++) { - s = Gui_Screens[i]; - if (s->VTABLE->HandlesKeyDown(s, key)) return; - } - - if ((key == KEY_ESCAPE || key == KEY_PAUSE) && !Gui_GetInputGrab()) { -#ifdef CC_BUILD_WEB - /* Can't do this in KeyUp, because pressing escape without having */ - /* explicitly disabled mouse lock means a KeyUp event isn't sent. */ - /* But switching to pause screen disables mouse lock, causing a KeyUp */ - /* event to be sent, triggering the active->closable case which immediately - /* closes the pause screen. Hence why the next KeyUp must be supressed. */ - suppressEscape = true; -#endif - PauseScreen_Show(); return; - } - - /* These should not be triggered multiple times when holding down */ - if (was) return; - if (HandleBlockKey(key)) { - } else if (HandleCoreKey(key)) { - } else if (LocalPlayer_HandlesKey(key)) { - } else { HandleHotkeyDown(key); } -} - -static void HandleInputUp(void* obj, int key) { - struct Screen* s; - int i; - - if (key == KeyBinds[KEYBIND_ZOOM_SCROLL]) Game_SetFov(Game_DefaultFov); -#ifdef CC_BUILD_WEB - /* When closing menus (which reacquires mouse focus) in key down, */ - /* this still leaves the cursor visible. But if this is instead */ - /* done in key up, the cursor disappears as expected. */ - if (key == KEY_ESCAPE && (s = Gui_GetClosable())) { - if (suppressEscape) { suppressEscape = false; return; } - Gui_Remove(s); return; - } -#endif - - for (i = 0; i < Gui_ScreensCount; i++) { - s = Gui_Screens[i]; - if (s->VTABLE->HandlesKeyUp(s, key)) return; - } - - if (Gui_GetInputGrab()) return; - if (key == KeyBinds[KEYBIND_DELETE_BLOCK]) MouseStateRelease(MOUSE_LEFT); - if (key == KeyBinds[KEYBIND_PLACE_BLOCK]) MouseStateRelease(MOUSE_RIGHT); - if (key == KeyBinds[KEYBIND_PICK_BLOCK]) MouseStateRelease(MOUSE_MIDDLE); -} - -static void HandleKeyPress(void* obj, int keyChar) { - struct Screen* s; - int i; - - for (i = 0; i < Gui_ScreensCount; i++) { - s = Gui_Screens[i]; - if (s->VTABLE->HandlesKeyPress(s, keyChar)) return; - } -} - -void InputHandler_Init(void) { - Event_RegisterMove(&PointerEvents.Moved, NULL, HandlePointerMove); - Event_RegisterInt(&PointerEvents.Down, NULL, HandlePointerDown); - Event_RegisterInt(&PointerEvents.Up, NULL, HandlePointerUp); - Event_RegisterInt(&InputEvents.Down, NULL, HandleInputDown); - Event_RegisterInt(&InputEvents.Up, NULL, HandleInputUp); - Event_RegisterInt(&InputEvents.Press, NULL, HandleKeyPress); - Event_RegisterFloat(&InputEvents.Wheel, NULL, HandleMouseWheel); - - Event_RegisterVoid(&UserEvents.HackPermissionsChanged, NULL, InputHandler_CheckZoomFov); - KeyBind_Init(); - Hotkeys_Init(); -} diff --git a/src/InputHandler.h b/src/InputHandler.h deleted file mode 100644 index 58c8ff77f..000000000 --- a/src/InputHandler.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef CC_INPUTHANDLER_H -#define CC_INPUTHANDLER_H -#include "Input.h" -/* Implements base handlers for mouse and keyboard input. - Copyright 2014-2019 ClassiCube | Licensed under BSD-3 -*/ -struct Screen; - -bool InputHandler_SetFOV(int fov); -void InputHandler_PickBlocks(void); -void InputHandler_Init(void); -void InputHandler_OnScreensChanged(void); -#endif