bsnes/ruby/input/mouse/rawinput.cpp

124 lines
3.7 KiB
C++
Executable File

#pragma once
struct InputMouseRawInput {
Input& input;
InputMouseRawInput(Input& input) : input(input) {}
uintptr handle = 0;
bool mouseAcquired = false;
struct Mouse {
shared_pointer<HID::Mouse> hid{new HID::Mouse};
int relativeX = 0;
int relativeY = 0;
int relativeZ = 0;
bool buttons[5] = {0};
} ms;
auto acquired() -> bool {
if(mouseAcquired) {
SetFocus((HWND)handle);
SetCapture((HWND)handle);
RECT rc;
GetWindowRect((HWND)handle, &rc);
ClipCursor(&rc);
}
return GetCapture() == (HWND)handle;
}
auto acquire() -> bool {
if(!mouseAcquired) {
mouseAcquired = true;
ShowCursor(false);
}
return acquired();
}
auto release() -> bool {
if(mouseAcquired) {
mouseAcquired = false;
ReleaseCapture();
ClipCursor(nullptr);
ShowCursor(true);
}
return true;
}
auto update(RAWINPUT* input) -> void {
if((input->data.mouse.usFlags & 1) == MOUSE_MOVE_RELATIVE) {
ms.relativeX += input->data.mouse.lLastX;
ms.relativeY += input->data.mouse.lLastY;
}
if(input->data.mouse.usButtonFlags & RI_MOUSE_WHEEL) {
ms.relativeZ += (int16_t)input->data.mouse.usButtonData;
}
if(input->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_1_DOWN) ms.buttons[0] = 1;
if(input->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_1_UP ) ms.buttons[0] = 0;
if(input->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_2_DOWN) ms.buttons[1] = 1;
if(input->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_2_UP ) ms.buttons[1] = 0;
if(input->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_3_DOWN) ms.buttons[2] = 1;
if(input->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_3_UP ) ms.buttons[2] = 0;
if(input->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_DOWN) ms.buttons[3] = 1;
if(input->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_UP ) ms.buttons[3] = 0;
if(input->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_DOWN) ms.buttons[4] = 1;
if(input->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_UP ) ms.buttons[4] = 0;
}
auto assign(uint groupID, uint inputID, int16_t value) -> void {
auto& group = ms.hid->group(groupID);
if(group.input(inputID).value() == value) return;
input.doChange(ms.hid, groupID, inputID, group.input(inputID).value(), value);
group.input(inputID).setValue(value);
}
auto poll(vector<shared_pointer<HID::Device>>& devices) -> void {
assign(HID::Mouse::GroupID::Axis, 0, ms.relativeX);
assign(HID::Mouse::GroupID::Axis, 1, ms.relativeY);
assign(HID::Mouse::GroupID::Axis, 2, ms.relativeZ);
//keys are intentionally reordered below:
//in ruby, button order is {left, middle, right, up, down}
assign(HID::Mouse::GroupID::Button, 0, ms.buttons[0]);
assign(HID::Mouse::GroupID::Button, 2, ms.buttons[1]);
assign(HID::Mouse::GroupID::Button, 1, ms.buttons[2]);
assign(HID::Mouse::GroupID::Button, 4, ms.buttons[3]);
assign(HID::Mouse::GroupID::Button, 3, ms.buttons[4]);
ms.relativeX = 0;
ms.relativeY = 0;
ms.relativeZ = 0;
devices.append(ms.hid);
}
auto initialize(uintptr handle) -> bool {
if(!handle) return false;
this->handle = handle;
ms.hid->setVendorID(HID::Mouse::GenericVendorID);
ms.hid->setProductID(HID::Mouse::GenericProductID);
ms.hid->setPathID(0);
ms.hid->axes().append("X");
ms.hid->axes().append("Y");
ms.hid->axes().append("Z");
ms.hid->buttons().append("Left");
ms.hid->buttons().append("Middle");
ms.hid->buttons().append("Right");
ms.hid->buttons().append("Up");
ms.hid->buttons().append("Down");
rawinput.updateMouse = {&InputMouseRawInput::update, this};
return true;
}
auto terminate() -> void {
rawinput.updateMouse.reset();
release();
}
};