-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
87808e8
commit 8ce58f2
Showing
5 changed files
with
202 additions
and
182 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
#pragma once | ||
|
||
#include <queue> | ||
#include <Geode/Geode.hpp> | ||
|
||
using namespace geode::prelude; | ||
|
||
enum GameAction : int { | ||
p1Jump = 0, | ||
p1Left = 1, | ||
p1Right = 2, | ||
p2Jump = 3, | ||
p2Left = 4, | ||
p2Right = 5 | ||
}; | ||
|
||
enum Player : bool { | ||
Player1 = 0, | ||
Player2 = 1 | ||
}; | ||
|
||
enum State : bool { | ||
Press = 0, | ||
Release = 1 | ||
}; | ||
|
||
struct InputEvent { | ||
LARGE_INTEGER time; | ||
PlayerButton inputType; | ||
bool inputState; | ||
bool player; | ||
}; | ||
|
||
struct Step { | ||
InputEvent input; | ||
double deltaFactor; | ||
bool endStep; | ||
}; | ||
|
||
extern std::queue<struct InputEvent> inputQueue; | ||
|
||
extern std::unordered_set<size_t> inputBinds[6]; | ||
extern std::unordered_set<USHORT> heldInputs; | ||
|
||
extern CRITICAL_SECTION inputQueueLock; | ||
extern CRITICAL_SECTION keybindsLock; | ||
|
||
extern bool enableRightClick; | ||
extern bool threadPriority; | ||
|
||
void inputThread(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
#include "includes.hpp" | ||
|
||
std::queue<struct InputEvent> inputQueue; | ||
|
||
std::unordered_set<size_t> inputBinds[6]; | ||
std::unordered_set<USHORT> heldInputs; | ||
|
||
CRITICAL_SECTION inputQueueLock; | ||
CRITICAL_SECTION keybindsLock; | ||
|
||
bool enableRightClick; | ||
bool threadPriority; | ||
|
||
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { | ||
LARGE_INTEGER time; | ||
PlayerButton inputType; | ||
bool inputState; | ||
bool player; | ||
|
||
QueryPerformanceCounter(&time); | ||
|
||
LPVOID pData; | ||
switch (uMsg) { | ||
case WM_INPUT: { | ||
UINT dwSize; | ||
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER)); | ||
|
||
auto lpb = std::unique_ptr<BYTE[]>(new BYTE[dwSize]); | ||
if (!lpb) { | ||
return 0; | ||
} | ||
if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb.get(), &dwSize, sizeof(RAWINPUTHEADER)) != dwSize) { | ||
log::debug("GetRawInputData does not return correct size"); | ||
} | ||
|
||
RAWINPUT* raw = (RAWINPUT*)lpb.get(); | ||
switch (raw->header.dwType) { | ||
case RIM_TYPEKEYBOARD: { | ||
USHORT vkey = raw->data.keyboard.VKey; | ||
inputState = raw->data.keyboard.Flags & RI_KEY_BREAK; | ||
|
||
if (vkey >= VK_NUMPAD0 && vkey <= VK_NUMPAD9) vkey -= 0x30; // make numpad numbers work with customkeybinds | ||
|
||
// cocos2d::enumKeyCodes corresponds directly to vkeys | ||
if (heldInputs.contains(vkey)) { | ||
if (!inputState) return 0; | ||
else heldInputs.erase(vkey); | ||
} | ||
|
||
bool shouldEmplace = true; | ||
player = Player1; | ||
|
||
EnterCriticalSection(&keybindsLock); | ||
|
||
if (inputBinds[p1Jump].contains(vkey)) inputType = PlayerButton::Jump; | ||
else if (inputBinds[p1Left].contains(vkey)) inputType = PlayerButton::Left; | ||
else if (inputBinds[p1Right].contains(vkey)) inputType = PlayerButton::Right; | ||
else { | ||
player = Player2; | ||
if (inputBinds[p2Jump].contains(vkey)) inputType = PlayerButton::Jump; | ||
else if (inputBinds[p2Left].contains(vkey)) inputType = PlayerButton::Left; | ||
else if (inputBinds[p2Right].contains(vkey)) inputType = PlayerButton::Right; | ||
else shouldEmplace = false; | ||
} | ||
if (!inputState) heldInputs.emplace(vkey); | ||
|
||
LeaveCriticalSection(&keybindsLock); | ||
|
||
if (!shouldEmplace) return 0; // has to be done outside of the critical section | ||
break; | ||
} | ||
case RIM_TYPEMOUSE: { | ||
USHORT flags = raw->data.mouse.usButtonFlags; | ||
bool shouldEmplace = true; | ||
player = Player1; | ||
inputType = PlayerButton::Jump; | ||
|
||
EnterCriticalSection(&keybindsLock); | ||
bool rc = enableRightClick; | ||
LeaveCriticalSection(&keybindsLock); | ||
|
||
if (flags & RI_MOUSE_BUTTON_1_DOWN) inputState = Press; | ||
else if (flags & RI_MOUSE_BUTTON_1_UP) inputState = Release; | ||
else { | ||
player = Player2; | ||
if (!rc) return 0; | ||
if (flags & RI_MOUSE_BUTTON_2_DOWN) inputState = Press; | ||
else if (flags & RI_MOUSE_BUTTON_2_UP) inputState = Release; | ||
else return 0; | ||
} | ||
break; | ||
} | ||
default: | ||
return 0; | ||
} | ||
break; | ||
} | ||
default: | ||
return DefWindowProcA(hwnd, uMsg, wParam, lParam); | ||
} | ||
|
||
EnterCriticalSection(&inputQueueLock); | ||
inputQueue.emplace(InputEvent{ time, inputType, inputState, player }); | ||
LeaveCriticalSection(&inputQueueLock); | ||
|
||
return 0; | ||
} | ||
|
||
void inputThread() { | ||
|
||
WNDCLASS wc = {}; | ||
wc.lpfnWndProc = WindowProc; | ||
wc.hInstance = GetModuleHandleA(NULL); | ||
wc.lpszClassName = "CBF"; | ||
|
||
RegisterClass(&wc); | ||
HWND hwnd = CreateWindow("CBF", "Raw Input Window", 0, 0, 0, 0, 0, HWND_MESSAGE, 0, wc.hInstance, 0); | ||
if (!hwnd) { | ||
const DWORD err = GetLastError(); | ||
log::error("Failed to create raw input window: {}", err); | ||
return; | ||
} | ||
|
||
RAWINPUTDEVICE dev[2]; | ||
dev[0].usUsagePage = 0x01; // generic desktop controls | ||
dev[0].usUsage = 0x02; // mouse | ||
dev[0].dwFlags = RIDEV_INPUTSINK; // allow inputs without being in the foreground | ||
dev[0].hwndTarget = hwnd; // raw input window | ||
|
||
dev[1].usUsagePage = 0x01; | ||
dev[1].usUsage = 0x06; // keyboard | ||
dev[1].dwFlags = RIDEV_INPUTSINK; | ||
dev[1].hwndTarget = hwnd; | ||
|
||
if (!RegisterRawInputDevices(dev, 2, sizeof(dev[0]))) { | ||
log::error("Failed to register raw input devices"); | ||
return; | ||
} | ||
|
||
if (threadPriority) SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); | ||
|
||
MSG msg; | ||
while (GetMessage(&msg, hwnd, 0, 0)) { | ||
DispatchMessage(&msg); | ||
} | ||
} |
Oops, something went wrong.