Port InputHandler and PickingHandler to C

This commit is contained in:
UnknownShadow200 2018-03-25 15:42:28 +11:00
parent d05f4ab214
commit 6430656cfe
17 changed files with 490 additions and 67 deletions

View File

@ -68,7 +68,7 @@ namespace ClassicalSharp {
}
}
public static bool CheckIsFree(Game game, BlockID block) {
static bool CheckIsFree(Game game, BlockID block) {
Vector3 pos = (Vector3)game.SelectedPos.TranslatedPos;
LocalPlayer p = game.LocalPlayer;
@ -99,21 +99,20 @@ namespace ClassicalSharp {
static bool PushbackPlace(Game game, AABB blockBB) {
LocalPlayer p = game.LocalPlayer;
Vector3 curPos = p.Position, adjPos = p.Position;
// Offset position by the closest face
PickedPos selected = game.SelectedPos;
if (selected.Face == BlockFace.XMax) {
BlockFace closestFace = game.SelectedPos.Face;
if (closestFace == BlockFace.XMax) {
adjPos.X = blockBB.Max.X + 0.5f;
} else if (selected.Face == BlockFace.ZMax) {
} else if (closestFace == BlockFace.ZMax) {
adjPos.Z = blockBB.Max.Z + 0.5f;
} else if (selected.Face == BlockFace.XMin) {
} else if (closestFace == BlockFace.XMin) {
adjPos.X = blockBB.Min.X - 0.5f;
} else if (selected.Face == BlockFace.ZMin) {
} else if (closestFace == BlockFace.ZMin) {
adjPos.Z = blockBB.Min.Z - 0.5f;
} else if (selected.Face == BlockFace.YMax) {
} else if (closestFace == BlockFace.YMax) {
adjPos.Y = blockBB.Min.Y + 1 + Entity.Adjustment;
} else if (selected.Face == BlockFace.YMin) {
} else if (closestFace == BlockFace.YMin) {
adjPos.Y = blockBB.Min.Y - p.Size.Y - Entity.Adjustment;
}

View File

@ -207,6 +207,7 @@
<ClInclude Include="Hotkeys.h" />
<ClInclude Include="IModel.h" />
<ClInclude Include="Input.h" />
<ClInclude Include="InputHandler.h" />
<ClInclude Include="Intersection.h" />
<ClInclude Include="Inventory.h" />
<ClInclude Include="IsometricDrawer.h" />
@ -280,6 +281,7 @@
<ClCompile Include="Gui.c" />
<ClCompile Include="HeldBlockRenderer.c" />
<ClCompile Include="Hotkeys.c" />
<ClCompile Include="InputHandler.c" />
<ClCompile Include="Inventory.c" />
<ClCompile Include="MapGenerator.c" />
<ClCompile Include="FrustumCulling.c" />

View File

@ -381,6 +381,9 @@
<ClInclude Include="HeldBlockRenderer.h">
<Filter>Header Files\Rendering</Filter>
</ClInclude>
<ClInclude Include="InputHandler.h">
<Filter>Header Files\Game</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Noise.c">
@ -599,5 +602,8 @@
<ClCompile Include="HeldBlockRenderer.c">
<Filter>Source Files\Rendering</Filter>
</ClCompile>
<ClCompile Include="InputHandler.c">
<Filter>Source Files\Game</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -39,7 +39,7 @@ bool Game_GetCursorVisible(void) { return Game_CursorVisible; }
void Game_SetCursorVisible(bool visible) {
/* Defer mouse visibility changes */
Game_realCursorVisible = visible;
if (Gui_OverlayCount > 0) return;
if (Gui_OverlaysCount > 0) return;
/* Only set the value when it has changed */
if (Game_CursorVisible == visible) return;

View File

@ -104,11 +104,11 @@ void Gui_Init(void) {
}
void Gui_Reset(void) {
UInt32 i;
for (i = 0; i < Gui_OverlayCount; i++) {
Int32 i;
for (i = 0; i < Gui_OverlaysCount; i++) {
Gui_Overlays[i]->Base.Free(&Gui_Overlays[i]->Base);
}
Gui_OverlayCount = 0;
Gui_OverlaysCount = 0;
}
void Gui_Free(void) {
@ -134,7 +134,7 @@ IGameComponent Gui_MakeGameComponent(void) {
}
Screen* Gui_GetActiveScreen(void) {
return Gui_OverlayCount > 0 ? Gui_Overlays[0] : Gui_GetUnderlyingScreen();
return Gui_OverlaysCount > 0 ? Gui_Overlays[0] : Gui_GetUnderlyingScreen();
}
Screen* Gui_GetUnderlyingScreen(void) {
@ -167,14 +167,14 @@ void Gui_RefreshHud(void) {
}
void Gui_ShowOverlay(Screen* overlay) {
if (Gui_OverlayCount == GUI_MAX_OVERLAYS) {
if (Gui_OverlaysCount == GUI_MAX_OVERLAYS) {
ErrorHandler_Fail("Cannot have more than 40 overlays");
}
bool visible = Game_GetCursorVisible();
if (Gui_OverlayCount == 0) Game_SetCursorVisible(true);
if (Gui_OverlaysCount == 0) Game_SetCursorVisible(true);
Gui_Overlays[Gui_OverlayCount++] = overlay;
if (Gui_OverlayCount == 1) Game_SetCursorVisible(visible); /* Save cursor visibility state */
Gui_Overlays[Gui_OverlaysCount++] = overlay;
if (Gui_OverlaysCount == 1) Game_SetCursorVisible(visible); /* Save cursor visibility state */
overlay->Base.Init(&overlay->Base);
}
@ -194,7 +194,7 @@ void Gui_RenderGui(Real64 delta) {
Gui_HUD->Base.Render(&Gui_HUD->Base, delta);
}
if (Gui_OverlayCount > 0) {
if (Gui_OverlaysCount > 0) {
Gui_Overlays[0]->Base.Render(&Gui_Overlays[0]->Base, delta);
}
GfxCommon_Mode3D();
@ -206,8 +206,8 @@ void Gui_OnResize(void) {
}
Gui_HUD->OnResize(&Gui_HUD->Base);
UInt32 i;
for (i = 0; i < Gui_OverlayCount; i++) {
Int32 i;
for (i = 0; i < Gui_OverlaysCount; i++) {
Gui_Overlays[i]->OnResize(&Gui_Overlays[i]->Base);
}
}

View File

@ -76,11 +76,10 @@ Screen* Gui_HUD;
Screen* Gui_Active;
#define GUI_MAX_OVERLAYS 40
Screen* Gui_Overlays[GUI_MAX_OVERLAYS];
UInt32 Gui_OverlayCount;
Int32 Gui_OverlaysCount;
Int32 Gui_CalcPos(UInt8 anchor, Int32 offset, Int32 size, Int32 axisLen);
bool Gui_Contains(Int32 recX, Int32 recY, Int32 width, Int32 height, Int32 x, Int32 y);
/* Creates game component implementation. */
IGameComponent Gui_MakeGameComponent(void);
/* Gets the screen that the user is currently interacting with.
This means if an overlay is active, it will be over the top of other screens. */

429
src/Client/InputHandler.c Normal file
View File

@ -0,0 +1,429 @@
#include "InputHandler.h"
#include "Utils.h"
#include "Hotkeys.h"
#include "ServerConnection.h"
#include "Game.h"
#include "Platform.h"
#include "ExtMath.h"
#include "Camera.h"
#include "Inventory.h"
#include "World.h"
#include "Event.h"
#include "GameMode.h"
#include "Window.h"
#include "Player.h"
#include "Chat.h"
#include "Funcs.h"
#include "Screens.h"
bool input_buttonsDown[3];
Int32 input_pickingId = -1;
Int32 input_normViewDists[] = { 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096 };
Int32 input_classicViewDists[] = { 8, 32, 128, 512 };
Key input_lastKey;
DateTime input_lastClick;
Real32 input_fovIndex = -1.0f;
bool InputHandler_IsMousePressed(MouseButton button) {
if (Mouse_IsPressed(button)) return true;
/* Key --> mouse mappings */
if (button == MouseButton_Left && KeyBind_IsPressed(KeyBind_MouseLeft)) return true;
if (button == MouseButton_Middle && KeyBind_IsPressed(KeyBind_MouseMiddle)) return true;
if (button == MouseButton_Right && KeyBind_IsPressed(KeyBind_MouseRight)) return true;
return false;
}
void InputHandler_ButtonStateUpdate(MouseButton button, bool pressed) {
/* defer getting the targeted entity as it's a costly operation */
if (input_pickingId == -1) {
Entity* p = &LocalPlayer_Instance.Base.Base;
input_pickingId = Entities_GetCloset(p);
}
EntityID id = (EntityID)input_pickingId;
ServerConnection_SendPlayerClick(button, pressed, id, &Game_SelectedPos);
input_buttonsDown[button] = pressed;
}
void InputHandler_ButtonStateChanged(MouseButton button, bool pressed) {
if (pressed) {
/* Can send multiple Pressed events */
InputHandler_ButtonStateUpdate(button, true);
} else {
if (!input_buttonsDown[button]) return;
InputHandler_ButtonStateUpdate(button, false);
}
}
void InputHandler_ScreenChanged(Screen* oldScreen, Screen* newScreen) {
if (oldScreen != NULL && oldScreen->HandlesAllInput) {
input_lastClick = Platform_CurrentUTCTime();
}
if (ServerConnection_SupportsPlayerClick) {
input_pickingId = -1;
InputHandler_ButtonStateChanged(MouseButton_Left, false);
InputHandler_ButtonStateChanged(MouseButton_Right, false);
InputHandler_ButtonStateChanged(MouseButton_Middle, false);
}
}
bool InputHandler_IsShutdown(Key key, Key last) {
if (key == Key_F4 && (last == Key_AltLeft || last == Key_AltRight)) return true;
/* On OSX, Cmd+Q should also terminate the process. */
#if CC_BUILD_OSX
return key == Key_Q && (last == Key_WinLeft || last == Key_WinRight);
#else
return false;
#endif
}
void InputHandler_Toggle(Key key, bool* target, const UInt8* enableMsg, const UInt8* disableMsg) {
*target = !(*target);
UInt8 msgBuffer[String_BufferSize(STRING_SIZE * 2)];
String msg = String_InitAndClearArray(msgBuffer);
String_AppendConst(&msg, (*target) ? enableMsg : disableMsg);
String_AppendConst(&msg, ". &ePress &a");
String_AppendConst(&msg, Key_Names[key]);
String_AppendConst(&msg, (*target) ? " &eto disable." : " &eto re-enable.");
Chat_Add(&msg);
}
void InputHandler_CycleDistanceForwards(Int32* viewDists, Int32 count) {
Int32 i;
for (i = 0; i < count; i++) {
Int32 dist = viewDists[i];
if (dist > Game_UserViewDistance) {
Game_SetViewDistance(dist, true); return;
}
}
Game_SetViewDistance(viewDists[0], true);
}
void InputHandler_CycleDistanceBackwards(Int32* viewDists, Int32 count) {
Int32 i;
for (i = count - 1; i >= 0; i--) {
Int32 dist = viewDists[i];
if (dist < Game_UserViewDistance) {
Game_SetViewDistance(dist, true); return;
}
}
Game_SetViewDistance(viewDists[count - 1], true);
}
bool InputHandler_SetFOV(Int32 fov, bool setZoom) {
if (Game_Fov == fov) return true;
HacksComp* h = &LocalPlayer_Instance.Hacks;
if (!h->Enabled || !h->CanAnyHacks || !h->CanUseThirdPersonCamera) return false;
Game_Fov = fov;
if (setZoom) Game_ZoomFov = fov;
Game_UpdateProjection();
return true;
}
bool InputHandler_DoFovZoom(Real32 deltaPrecise) {
if (!KeyBind_IsPressed(KeyBind_ZoomScrolling)) return false;
HacksComp* h = &LocalPlayer_Instance.Hacks;
if (!h->Enabled || !h->CanAnyHacks || !h->CanUseThirdPersonCamera) return false;
if (input_fovIndex == -1.0f) input_fovIndex = Game_ZoomFov;
input_fovIndex -= deltaPrecise * 5.0f;
Math_Clamp(input_fovIndex, 1.0f, Game_DefaultFov);
return InputHandler_SetFOV((Int32)input_fovIndex, true);
}
bool InputHandler_HandleCoreKey(Key key) {
if (key == KeyBind_Get(KeyBind_HideGui)) {
Game_HideGui = !Game_HideGui;
} else if (key == KeyBind_Get(KeyBind_HideFps)) {
Game_ShowFPS = !Game_ShowFPS;
} else if (key == KeyBind_Get(KeyBind_Fullscreen)) {
UInt8 state = Window_GetWindowState();
if (state != WINDOW_STATE_MAXIMISED) {
bool fullscreen = state == WINDOW_STATE_FULLSCREEN;
Window_SetWindowState(fullscreen ? WINDOW_STATE_NORMAL : WINDOW_STATE_FULLSCREEN);
}
} else if (key == KeyBind_Get(KeyBind_SmoothCamera)) {
InputHandler_Toggle(key, &Game_SmoothCamera,
" &eSmooth camera is &aenabled",
" &eSmooth camera is &cdisabled");
} else if (key == KeyBind_Get(KeyBind_AxisLines)) {
InputHandler_Toggle(key, &Game_ShowAxisLines,
" &eAxis lines (&4X&e, &2Y&e, &1Z&e) now show",
" &eAxis lines no longer show");
} else if (key == KeyBind_Get(KeyBind_Autorotate)) {
InputHandler_Toggle(key, &Game_AutoRotate,
" &eAuto rotate is &aenabled",
" &eAuto rotate is &cdisabled");
} else if (key == KeyBind_Get(KeyBind_ThirdPerson)) {
Camera_CycleActive();
} else if (key == KeyBind_Get(KeyBind_ToggleFog)) {
Int32* viewDists = Game_UseClassicOptions ? input_classicViewDists : input_normViewDists;
Int32 count = Game_UseClassicOptions ? Array_Elems(input_classicViewDists) : Array_Elems(input_normViewDists);
if (Key_IsShiftPressed()) {
InputHandler_CycleDistanceBackwards(viewDists, count);
} else {
InputHandler_CycleDistanceForwards(viewDists, count);
}
} else if ((key == KeyBind_Get(KeyBind_PauseOrExit) || key == Key_Pause) && World_Blocks != NULL) {
Screen* screen = PauseScreen_MakeInstance();
Gui_SetNewScreen(screen);
} else if (GameMode_HandlesKeyDown(key)) {
} else if (key == KeyBind_Get(KeyBind_IDOverlay)) {
if (Gui_OverlaysCount > 0) return true;
Gui_ShowOverlay(new TexIdsOverlay());
} else {
return false;
}
return true;
}
bool InputHandler_TouchesSolid(BlockID b) { return Block_Collide[b] == COLLIDE_SOLID; }
bool InputHandler_PushbackPlace(AABB* blockBB) {
Entity* p = &LocalPlayer_Instance.Base.Base;
HacksComp* hacks = &LocalPlayer_Instance.Hacks;
Vector3 curPos = p->Position, adjPos = p->Position;
/* Offset position by the closest face */
Face closestFace = Game_SelectedPos.ClosestFace;
if (closestFace == FACE_XMAX) {
adjPos.X = blockBB->Max.X + 0.5f;
} else if (closestFace == FACE_ZMAX) {
adjPos.Z = blockBB->Max.Z + 0.5f;
} else if (closestFace == FACE_XMIN) {
adjPos.X = blockBB->Min.X - 0.5f;
} else if (closestFace == FACE_ZMIN) {
adjPos.Z = blockBB->Min.Z - 0.5f;
} else if (closestFace == FACE_YMAX) {
adjPos.Y = blockBB->Min.Y + 1 + ENTITY_ADJUSTMENT;
} else if (closestFace == FACE_YMIN) {
adjPos.Y = blockBB->Min.Y - p->Size.Y - ENTITY_ADJUSTMENT;
}
/* exclude exact map boundaries, otherwise player can get stuck outside map */
bool validPos =
adjPos.X > 0.0f && adjPos.Y >= 0.0f && adjPos.Z > 0.0f &&
adjPos.X < World_Width && adjPos.Z < World_Length;
if (!validPos) return false;
p->Position = adjPos;
AABB bounds; Entity_GetBounds(p, &bounds);
if (!hacks->Noclip && Entity_TouchesAny(&bounds, InputHandler_TouchesSolid)) {
p->Position = curPos;
return false;
}
p->Position = curPos;
LocationUpdate update; LocationUpdate_MakePos(&update, adjPos, false);
p->VTABLE->SetLocation(p, &update, false);
return true;
}
bool InputHandler_IntersectsOthers(Vector3 pos, BlockID block) {
AABB blockBB;
Vector3_Add(&blockBB.Min, &pos, &Block_MinBB[block]);
Vector3_Add(&blockBB.Max, &pos, &Block_MaxBB[block]);
Int32 id;
for (id = 0; id < ENTITIES_SELF_ID; id++) {
Entity* entity = Entities_List[id];
if (entity == NULL) continue;
AABB bounds; Entity_GetBounds(entity, &bounds);
bounds.Min.Y += 1.0f / 32.0f; /* when player is exactly standing on top of ground */
if (AABB_Intersects(&bounds, &blockBB)) return true;
}
return false;
}
bool InputHandler_CheckIsFree(BlockID block) {
Vector3 pos; Vector3I_ToVector3(&pos, &Game_SelectedPos.TranslatedPos);
Entity* p = &LocalPlayer_Instance.Base.Base;
HacksComp* hacks = &LocalPlayer_Instance.Hacks;
if (Block_Collide[block] != COLLIDE_SOLID) return true;
if (InputHandler_IntersectsOthers(pos, block)) return false;
Vector3 nextPos = LocalPlayer_Instance.Interp.Next.Pos;
AABB blockBB;
Vector3_Add(&blockBB.Min, &pos, &Block_MinBB[block]);
Vector3_Add(&blockBB.Max, &pos, &Block_MaxBB[block]);
/* NOTE: Need to also test against nextPos here, otherwise player can
fall through the block at feet as collision is performed against nextPos */
AABB localBB; AABB_Make(&localBB, &p->Position, &p->Size);
localBB.Min.Y = min(nextPos.Y, localBB.Min.Y);
if (hacks->Noclip || !AABB_Intersects(&localBB, &blockBB)) return true;
if (hacks->CanPushbackBlocks && hacks->PushbackPlacing && hacks->Enabled) {
return InputHandler_PushbackPlace(&blockBB);
}
localBB.Min.Y += 0.25f + ENTITY_ADJUSTMENT;
if (AABB_Intersects(&localBB, &blockBB)) return false;
/* Push player upwards when they are jumping and trying to place a block underneath them */
nextPos.Y = pos.Y + Block_MaxBB[block].Y + ENTITY_ADJUSTMENT;
LocationUpdate update; LocationUpdate_MakePos(&update, nextPos, false);
p->VTABLE->SetLocation(p, &update, false);
return true;
}
void InputHandler_PickBlocks(bool cooldown, bool left, bool middle, bool right) {
DateTime now = Platform_CurrentUTCTime();
Int64 delta = DateTime_MsBetween(&input_lastClick, &now);
if (cooldown && delta < 250) return; /* 4 times per second */
input_lastClick = now;
if (ServerConnection_SupportsPlayerClick && !Gui_GetActiveScreen()->HandlesAllInput) {
input_pickingId = -1;
InputHandler_ButtonStateChanged(MouseButton_Left, left);
InputHandler_ButtonStateChanged(MouseButton_Right, right);
InputHandler_ButtonStateChanged(MouseButton_Middle, middle);
}
if (Gui_GetActiveScreen()->HandlesAllInput || !Inventory_CanPick) return;
if (left) {
if (GameMode_PickingLeft()) return;
Vector3I pos = Game_SelectedPos.BlockPos;
if (!Game_SelectedPos.Valid || !World_IsValidPos_3I(pos)) return;
BlockID old = World_GetBlock_3I(pos);
if (Block_Draw[old] == DRAW_GAS || !Block_CanDelete[old]) return;
GameMode_PickLeft(old);
} else if (right) {
if (GameMode_PickingRight()) return;
Vector3I pos = Game_SelectedPos.TranslatedPos;
if (!Game_SelectedPos.Valid || !World_IsValidPos_3I(pos)) return;
BlockID old = World_GetBlock_3I(pos);
BlockID block = Inventory_SelectedBlock;
if (Game_AutoRotate) { block = AutoRotate_RotateBlock(block); }
if (Game_CanPick(old) || !Block_CanPlace[block]) return;
/* air-ish blocks can only replace over other air-ish blocks */
if (Block_Draw[block] == DRAW_GAS && Block_Draw[old] != DRAW_GAS) return;
if (!InputHandler_CheckIsFree(block)) return;
GameMode_PickRight(old, block);
} else if (middle) {
Vector3I pos = Game_SelectedPos.BlockPos;
if (!Game_SelectedPos.Valid || !World_IsValidPos_3I(pos)) return;
BlockID old = World_GetBlock_3I(pos);
GameMode_PickMiddle(old);
}
}
void InputHandler_MouseWheel(void* obj, Real32 delta) {
GuiElement* active = &Gui_GetActiveScreen()->Base;
if (active->HandlesMouseScroll(active, delta)) return;
bool hotbar = Key_IsAltPressed() || Key_IsControlPressed() || Key_IsShiftPressed();
if (!hotbar && Camera_ActiveCamera->Zoom(delta)) return;
if (InputHandler_DoFovZoom(delta) || !Inventory_CanChangeHeldBlock) return;
game.Gui.hudScreen.hotbar.HandlesMouseScroll(delta);
}
void InputHandler_MouseMove(void* obj, Int32 xDelta, Int32 yDelta) {
GuiElement* active = &Gui_GetActiveScreen()->Base;
active->HandlesMouseMove(active, Mouse_X, Mouse_Y);
}
void InputHandler_MouseDown(void* obj, MouseButton button) {
GuiElement* active = &Gui_GetActiveScreen()->Base;
if (!active->HandlesMouseDown(active, Mouse_X, Mouse_Y, button)) {
bool left = button == MouseButton_Left;
bool middle = button == MouseButton_Middle;
bool right = button == MouseButton_Right;
InputHandler_PickBlocks(false, left, middle, right);
} else {
input_lastClick = Platform_CurrentUTCTime();
}
}
void InputHandler_MouseUp(void* obj, MouseButton button) {
GuiElement* active = &Gui_GetActiveScreen()->Base;
if (!active->HandlesMouseUp(active, Mouse_X, Mouse_Y, button)) {
if (ServerConnection_SupportsPlayerClick && button <= MouseButton_Middle) {
input_pickingId = -1;
InputHandler_ButtonStateChanged(button, false);
}
}
}
bool InputHandler_SimulateMouse(Key key, bool pressed) {
Key left = KeyBind_Get(KeyBind_MouseLeft);
Key middle = KeyBind_Get(KeyBind_MouseMiddle);
Key right = KeyBind_Get(KeyBind_MouseRight);
if (!(key == left || key == middle || key == right)) return false;
MouseButton btn = key == left ? MouseButton_Left : key == middle ? MouseButton_Middle : MouseButton_Right;
if (pressed) { InputHandler_MouseDown(NULL, btn); }
else { InputHandler_MouseUp(NULL, btn); }
return true;
}
void InputHandler_KeyDown(void* obj, Key key) {
if (InputHandler_SimulateMouse(key, true)) return;
GuiElement* active = &Gui_GetActiveScreen()->Base;
Key last = input_lastKey; input_lastKey = key;
if (InputHandler_IsShutdown(key, last)) {
/* TODO: Do we need a separate exit function in Game class? */
Window_Close();
} else if (key == KeyBind_Get(KeyBind_Screenshot)) {
Game_ScreenshotRequested = true;
} else if (active->HandlesKeyDown(active, key)) {
} else if (InputHandler_HandleCoreKey(key)) {
} else if (LocalPlayer_Instance.Input.Handles(key)) {
} else {
UInt8 textBuffer[String_BufferSize(STRING_SIZE)];
String text = String_InitAndClearArray(textBuffer);
bool more;
if (!Hotkeys_IsHotkey(key, &text, &more)) return;
if (!more) {
ServerConnection_SendChat(&text);
} else if (Gui_Active == NULL) {
HUDScreen_OpenInput(Gui_HUD, &text);
}
}
}
void InputHandler_KeyUp(void* obj, Key key) {
if (InputHandler_SimulateMouse(key, false)) return;
if (key == KeyBind_Get(KeyBind_ZoomScrolling)) {
InputHandler_SetFOV(Game_DefaultFov, false);
}
GuiElement* active = &Gui_GetActiveScreen()->Base;
active->HandlesKeyUp(active, key);
}
void InputHandler_KeyPress(void* obj, Int32 keyChar) {
GuiElement* active = &Gui_GetActiveScreen()->Base;
active->HandlesKeyPress(active, (UInt8)keyChar);
}
void InputHandler_Init(void) {
Event_RegisterReal32(&MouseEvents_Wheel, NULL, InputHandler_MouseWheel);
Event_RegisterMouseMove(&MouseEvents_Moved, NULL, InputHandler_MouseMove);
Event_RegisterInt32(&MouseEvents_Down, NULL, InputHandler_MouseDown);
Event_RegisterInt32(&MouseEvents_Up, NULL, InputHandler_MouseUp);
Event_RegisterInt32(&KeyEvents_Down, NULL, InputHandler_KeyDown);
Event_RegisterInt32(&KeyEvents_Up, NULL, InputHandler_KeyUp);
Event_RegisterInt32(&KeyEvents_Press, NULL, InputHandler_KeyPress);
KeyBind_Init();
Hotkeys_Init();
}

11
src/Client/InputHandler.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef CC_INPUTHANDLER_H
#define CC_INPUTHANDLER_H
#include "Typedefs.h"
/* Implements base handlers for mouse and keyboard input.
Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
*/
bool InputHandler_SetFOV(Int32 fov, bool setZoom);
void InputHandler_PickBlocks(bool cooldown, bool left, bool middle, bool right);
void InputHandler_Init(void);
#endif

View File

@ -6,6 +6,7 @@
#include "World.h"
#include "Funcs.h"
#include "Platform.h"
#include "BlockID.h"
Real32 PickedPos_dist;
void PickedPos_TestAxis(PickedPos* pos, Real32 dAxis, Face fAxis) {

View File

@ -3,29 +3,20 @@
#include "Typedefs.h"
#include "Constants.h"
#include "Vectors.h"
#include "BlockID.h"
/* Data for picking/selecting block by the user, and clipping the camera.
Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
*/
/* Describes the picked/selected block by the user and its position. */
typedef struct PickedPos_ {
/* Minimum world coordinates of the block's bounding box.*/
Vector3 Min;
/* Maximum world coordinates of the block's bounding box. */
Vector3 Max;
/* Exact world coordinates at which the ray intersected this block. */
Vector3 Intersect;
/* Integer world coordinates of the block. */
Vector3I BlockPos;
/* Integer world coordinates of the neighbouring block that is closest to the player. */
Vector3I TranslatedPos;
/* Whether this instance actually has a selected block currently. */
bool Valid;
/* Face of the picked block that is closet to the player. */
Face ClosestFace;
/* Block ID of the picked block. */
BlockID Block;
Vector3 Min; /* Minimum coords of the block's bounding box.*/
Vector3 Max; /* Maximum coords of the block's bounding box. */
Vector3 Intersect; /* Coords at which the ray intersected this block. */
Vector3I BlockPos; /* Coords of the block */
Vector3I TranslatedPos; /* Coords of the neighbouring block that is closest to the player */
bool Valid; /* Whether this instance actually has a selected block currently */
Face ClosestFace; /* Face of the picked block that is closet to the player */
BlockID Block; /* Block ID of the picked block */
} PickedPos;
/* Implements a voxel ray tracer
@ -46,9 +37,7 @@ typedef struct RayTracer_ {
Vector3 tMax, tDelta;
} RayTracer;
/* Mark as having a selected block, and calculates the closest face of the selected block's position. */
void PickedPos_SetAsValid(PickedPos* pos, RayTracer* t, Vector3 intersect);
/* Marks as not having a selected block. */
void PickedPos_SetAsInvalid(PickedPos* pos);
void RayTracer_SetVectors(RayTracer* t, Vector3 origin, Vector3 dir);
void RayTracer_Step(RayTracer* t);

View File

@ -1651,4 +1651,9 @@ IGameComponent HUDScreen_MakeComponent(void) {
IGameComponent comp = IGameComponent_MakeEmpty();
comp.Ready = HUDScreen_Ready;
return comp;
}
void HUDScreen_OpenInput(Screen* hud, STRING_PURE String* text) {
Screen* chat = ((HUDScreen*)hud)->Chat;
ChatScreen_OpenInput((ChatScreen*)chat, text);
}

View File

@ -15,6 +15,7 @@ Screen* LoadingScreen_MakeInstance(STRING_PURE String* title, STRING_PURE String
Screen* GeneratingScreen_MakeInstance(void);
Screen* HUDScreen_MakeInstance(void);
IGameComponent HUDScreen_MakeComponent(void);
void HUDScreen_OpenInput(Screen* hud, STRING_PURE String* text);
Screen* OptionsGroupScreen_MakeInstance(void);
Screen* PauseScreen_MakeInstance(void);

View File

@ -2,10 +2,9 @@
#define CC_SERVERCONNECTION_H
#include "Typedefs.h"
#include "String.h"
#include "Vectors.h"
#include "Input.h"
#include "GameStructs.h"
#include "PickedPosRenderer.h"
#include "Picking.h"
/* Represents a connection to either a singleplayer or multiplayer server.
Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
*/

View File

@ -25,10 +25,7 @@ Texture Texture_From(GfxResourceID id, Int32 x, Int32 y, Int32 width, Int32 heig
}
Texture Texture_MakeInvalid(void) {
Texture tex;
tex.ID = NULL;
tex.X = 0; tex.Y = 0; tex.Width = 0; tex.Height = 0;
tex.U1 = 0.0f; tex.V1 = 0.0f; tex.U2 = 0.0f; tex.V2 = 0.0f;
Texture tex = { NULL, 0, 0, 0, 0, 0.0f, 0.0f, 0.0f, 0.0f };
return tex;
}

View File

@ -18,17 +18,11 @@ typedef struct Texture_ {
Real32 U2, V2; /* Texture coordinates of bottom right corner. */
} Texture;
/* Creates a texture, with U1 and V1 being set to 0. */
Texture Texture_FromOrigin(GfxResourceID id, Int32 x, Int32 y, Int32 width, Int32 height, Real32 u2, Real32 v2);
/* Creates a texture, with U1/V1/U2/V2 using the input rectangle. */
Texture Texture_FromRec(GfxResourceID id, Int32 x, Int32 y, Int32 width, Int32 height, TextureRec rec);
/* Creates a texture. */
Texture Texture_From(GfxResourceID id, Int32 x, Int32 y, Int32 width, Int32 height, Real32 u1, Real32 u2, Real32 v1, Real32 v2);
/* Makes an invalid texture. */
Texture Texture_MakeInvalid(void);
/* Renders this texture to the screen. */
void Texture_Render(Texture* tex);
/* Renders this texture to the screen, with the given colour as a shade. */
void Texture_RenderShaded(Texture* tex, PackedCol shadeCol);
#endif

View File

@ -49,11 +49,10 @@ bool Utils_IsValidInputChar(UInt8 c, bool supportsCP437) {
}
bool Utils_IsUrlPrefix(STRING_PURE String* value, Int32 index) {
String httpStr = String_FromConst("http://");
String httpsStr = String_FromConst("https://");
Int32 http = String_IndexOfString(value, &httpStr);
Int32 https = String_IndexOfString(value, &httpsStr);
return http == index || https == index;
String http = String_FromConst("http://");
String https = String_FromConst("https://");
return String_IndexOfString(value, &http) == index
|| String_IndexOfString(value, &https) == index;
}
Int32 Utils_AccumulateWheelDelta(Real32* accmulator, Real32 delta) {
@ -74,11 +73,4 @@ UInt8 Utils_GetSkinType(Bitmap* bmp) {
UInt32 pixel = Bitmap_GetPixel(bmp, 54 * scale, 20 * scale);
UInt8 alpha = (UInt8)(pixel >> 24);
return alpha >= 127 ? SKIN_TYPE_64x64 : SKIN_TYPE_64x64_SLIM;
}
bool Utils_IsUrlPrefix(STRING_PURE String* str, Int32 index) {
String http = String_FromConst("http://");
String https = String_FromConst("https://");
return String_IndexOfString(str, &http) == index
|| String_IndexOfString(str, &https) == index;
}

View File

@ -34,5 +34,4 @@ Int32 Utils_AccumulateWheelDelta(Real32* accmulator, Real32 delta);
#define Utils_AdjViewDist(value) ((Int32)(1.4142135f * (value)))
UInt8 Utils_GetSkinType(Bitmap* bmp);
bool Utils_IsUrlPrefix(STRING_PURE String* str, Int32 index);
#endif