Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Raw mouse input support #798

Merged
merged 9 commits into from
Feb 21, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 43 additions & 11 deletions src/graphic/Fast3D/gfx_dxgi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@
#define NANOSECOND_IN_SECOND 1000000000
#define _100NANOSECONDS_IN_SECOND 10000000

#ifndef HID_USAGE_PAGE_GENERIC
#define HID_USAGE_PAGE_GENERIC ((unsigned short)0x01)
#endif
#ifndef HID_USAGE_GENERIC_MOUSE
#define HID_USAGE_GENERIC_MOUSE ((unsigned short)0x02)
#endif

using namespace Microsoft::WRL; // For ComPtr

static struct {
Expand Down Expand Up @@ -93,6 +100,8 @@ static struct {
LARGE_INTEGER previous_present_time;
bool is_mouse_captured;
bool in_focus;
RAWINPUTDEVICE raw_input_device[1];
POINT raw_mouse_delta_buf;

void (*on_fullscreen_changed)(bool is_now_fullscreen);
bool (*on_key_down)(int scancode);
Expand Down Expand Up @@ -425,6 +434,19 @@ static LRESULT CALLBACK gfx_dxgi_wnd_proc(HWND h_wnd, UINT message, WPARAM w_par
case WM_MOUSEWHEEL:
dxgi.mouse_wheel[1] = GET_WHEEL_DELTA_WPARAM(w_param) / WHEEL_DELTA;
break;
case WM_INPUT: {
if (dxgi.is_mouse_captured && dxgi.in_focus) {
uint32_t size = sizeof(RAWINPUT);
static RAWINPUT raw[sizeof(RAWINPUT)];
GetRawInputData((HRAWINPUT)l_param, RID_INPUT, raw, &size, sizeof(RAWINPUTHEADER));

if (raw->header.dwType == RIM_TYPEMOUSE) {
dxgi.raw_mouse_delta_buf.x += raw->data.mouse.lLastX;
dxgi.raw_mouse_delta_buf.y += raw->data.mouse.lLastY;
}
}
break;
}
case WM_DROPFILES:
DragQueryFileA((HDROP)w_param, 0, fileName, 256);
Ship::Context::GetInstance()->GetConsoleVariables()->SetString(CVAR_DROPPED_FILE, fileName);
Expand Down Expand Up @@ -527,6 +549,13 @@ void gfx_dxgi_init(const char* game_name, const char* gfx_api_name, bool start_i
}

DragAcceptFiles(dxgi.h_wnd, TRUE);

// Mouse init
dxgi.raw_input_device[0].usUsagePage = HID_USAGE_PAGE_GENERIC;
dxgi.raw_input_device[0].usUsage = HID_USAGE_GENERIC_MOUSE;
dxgi.raw_input_device[0].dwFlags = RIDEV_INPUTSINK;
dxgi.raw_input_device[0].hwndTarget = dxgi.h_wnd;
RegisterRawInputDevices(dxgi.raw_input_device, 1, sizeof(dxgi.raw_input_device[0]));
}

static void gfx_dxgi_set_fullscreen_changed_callback(void (*on_fullscreen_changed)(bool is_now_fullscreen)) {
Expand Down Expand Up @@ -572,19 +601,22 @@ static void gfx_dxgi_get_mouse_pos(int32_t* x, int32_t* y) {
}

static void gfx_dxgi_get_mouse_delta(int32_t* x, int32_t* y) {
if (dxgi.is_mouse_captured && dxgi.in_focus) {
POINT p;
GetCursorPos(&p);
ScreenToClient(dxgi.h_wnd, &p);
int32_t centerX, centerY;
centerX = dxgi.current_width / 2;
centerY = dxgi.current_height / 2;
*x = p.x - centerX;
*y = p.y - centerY;
SetCursorPos(dxgi.posX + centerX, dxgi.posY + centerY);
} else {
if (!dxgi.in_focus) {
*x = 0;
*y = 0;
} else if (dxgi.is_mouse_captured) {
*x = dxgi.raw_mouse_delta_buf.x;
*y = dxgi.raw_mouse_delta_buf.y;
dxgi.raw_mouse_delta_buf.x = 0;
dxgi.raw_mouse_delta_buf.y = 0;
} else {
static int32_t prev_x = 0, prev_y = 0;
int32_t current_x, current_y;
gfx_dxgi_get_mouse_pos(&current_x, &current_y);
*x = current_x - prev_x;
*y = current_y - prev_y;
prev_x = current_x;
prev_y = current_y;
}
}

Expand Down
Loading