Files
BlitzNext/Runtime/gfx/gxinput.cpp
T
Michael Fabian 'Xaymar' Dirks a16218e1d5 runtime: CMake-ify gx
2019-01-18 17:03:37 +01:00

405 lines
9.2 KiB
C++

#pragma once
#include "gxinput.hpp"
#include "gxruntime.hpp"
#include "std.hpp"
static const int QUE_SIZE = 32;
class Device : public gxDevice {
public:
bool acquired;
gxInput* input;
LPDIRECTINPUTDEVICE8 device;
Device(gxInput* i, LPDIRECTINPUTDEVICE8 d) : input(i), acquired(false), device(d) {}
virtual ~Device()
{
device->Release();
//device->Release();
}
bool acquire()
{
return device->Acquire() >= 0;
//return acquired=device->Acquire()>=0;
}
void unacquire()
{
device->Unacquire();
//device->Unacquire();
acquired = false;
}
};
class Keyboard : public Device {
public:
Keyboard(gxInput* i, LPDIRECTINPUTDEVICE8 d) : Device(i, d) {}
void update()
{
if (!acquired) {
input->runtime->idle();
return;
}
int k, cnt = 32;
DIDEVICEOBJECTDATA data[32], *curr;
if (device->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), data, (DWORD*)&cnt, 0) < 0)
return;
curr = data;
for (k = 0; k < cnt; ++curr, ++k) {
int n = curr->dwOfs;
if (!n || n > 255)
continue;
if (curr->dwData & 0x80)
downEvent(n);
else
upEvent(n);
}
}
};
class Mouse : public Device {
public:
Mouse(gxInput* i, LPDIRECTINPUTDEVICE8 d) : Device(i, d) {}
void update()
{
if (!acquired) {
input->runtime->idle();
return;
}
DIMOUSESTATE state;
if (device->GetDeviceState(sizeof(state), &state) < 0)
return;
if (gxGraphics* g = input->runtime->graphics) {
int mx = axis_states[0] + state.lX;
int my = axis_states[1] + state.lY;
if (mx < 0)
mx = 0;
else if (mx >= g->getWidth())
mx = g->getWidth() - 1;
if (my < 0)
my = 0;
else if (my >= g->getHeight())
my = g->getHeight() - 1;
axis_states[0] = mx;
axis_states[1] = my;
axis_states[2] += state.lZ;
}
for (int k = 0; k < 3; ++k) {
setDownState(k + 1, state.rgbButtons[k] & 0x80 ? true : false);
}
}
};
class Joystick : public Device {
public:
int type, poll_time;
int mins[12], maxs[12];
Joystick(gxInput* i, LPDIRECTINPUTDEVICE8 d, int t) : Device(i, d), type(t), poll_time(0)
{
for (int k = 0; k < 12; ++k) {
//initialize joystick axis ranges (d'oh!)
DIPROPRANGE range;
range.diph.dwSize = sizeof(DIPROPRANGE);
range.diph.dwHeaderSize = sizeof(DIPROPHEADER);
range.diph.dwObj = k * 4 + 12;
range.diph.dwHow = DIPH_BYOFFSET;
if (d->GetProperty(DIPROP_RANGE, &range.diph) < 0) {
mins[k] = 0;
maxs[k] = 65535;
continue;
}
mins[k] = range.lMin;
maxs[k] = range.lMax - range.lMin;
}
}
void update()
{
unsigned tm = timeGetTime();
if (tm - poll_time < 3)
return;
if (device->Poll() < 0) {
acquired = false;
input->runtime->idle();
acquire();
if (device->Poll() < 0)
return;
}
poll_time = tm;
DIJOYSTATE state;
if (device->GetDeviceState(sizeof(state), &state) < 0)
return;
axis_states[0] = (state.lX - mins[0]) / (float)maxs[0] * 2 - 1;
axis_states[1] = (state.lY - mins[1]) / (float)maxs[1] * 2 - 1;
axis_states[2] = (state.lZ - mins[2]) / (float)maxs[2] * 2 - 1;
axis_states[3] = (state.rglSlider[0] - mins[6]) / (float)maxs[6] * 2 - 1;
axis_states[4] = (state.rglSlider[1] - mins[7]) / (float)maxs[7] * 2 - 1;
axis_states[5] = (state.lRx - mins[3]) / (float)maxs[3] * 2 - 1;
axis_states[6] = (state.lRy - mins[4]) / (float)maxs[4] * 2 - 1;
axis_states[7] = (state.lRz - mins[5]) / (float)maxs[5] * 2 - 1;
if ((state.rgdwPOV[0] & 0xffff) == 0xffff)
axis_states[8] = -1;
else
axis_states[8] = floor(state.rgdwPOV[0] / 100.0f + .5f);
for (int k = 0; k < 31; ++k) {
setDownState(k + 1, state.rgbButtons[k] & 0x80 ? true : false);
}
}
};
static Keyboard* keyboard;
static Mouse* mouse;
static vector<Joystick*> joysticks;
static Keyboard* createKeyboard(gxInput* input)
{
LPDIRECTINPUTDEVICE8 dev;
if (input->dirInput->CreateDevice(GUID_SysKeyboard, &dev, NULL) >= 0) {
if (dev->SetCooperativeLevel(input->runtime->hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE) >= 0) {
if (dev->SetDataFormat(&c_dfDIKeyboard) >= 0) {
DIPROPDWORD dword;
memset(&dword, 0, sizeof(dword));
dword.diph.dwSize = sizeof(DIPROPDWORD);
dword.diph.dwHeaderSize = sizeof(DIPROPHEADER);
dword.diph.dwObj = 0;
dword.diph.dwHow = DIPH_DEVICE;
dword.dwData = 32;
if (dev->SetProperty(DIPROP_BUFFERSIZE, &dword.diph) >= 0) {
return new Keyboard(input, dev);
} else {
// input->runtime->debugInfo( "keyboard: SetProperty failed" );
}
} else {
// input->runtime->debugInfo( "keyboard: SetDataFormat failed" );
}
return new Keyboard(input, dev);
} else {
input->runtime->debugInfo("keyboard: SetCooperativeLevel failed");
}
dev->Release();
} else {
input->runtime->debugInfo("keyboard: CreateDeviceEx failed");
}
return 0;
}
static Mouse* createMouse(gxInput* input)
{
LPDIRECTINPUTDEVICE8 dev;
if (input->dirInput->CreateDevice(GUID_SysMouse, &dev, 0) >= 0) {
if (dev->SetCooperativeLevel(input->runtime->hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE) >= 0) {
if (dev->SetDataFormat(&c_dfDIMouse) >= 0) {
return new Mouse(input, dev);
} else {
// input->runtime->debugInfo( "mouse: SetDataFormat failed" );
}
return new Mouse(input, dev);
} else {
input->runtime->debugInfo("mouse: SetCooperativeLevel failed");
}
dev->Release();
} else {
input->runtime->debugInfo("mouse: CreateDeviceEx failed");
}
return 0;
}
static Joystick* createJoystick(gxInput* input, LPCDIDEVICEINSTANCE devinst)
{
LPDIRECTINPUTDEVICE8 dev;
if (input->dirInput->CreateDevice(devinst->guidInstance, &dev, 0) >= 0) {
if (dev->SetCooperativeLevel(input->runtime->hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE) >= 0) {
if (dev->SetDataFormat(&c_dfDIJoystick) >= 0) {
int t = ((devinst->dwDevType >> 8) & 0xff) == DI8DEVCLASS_GAMECTRL ? 1 : 2;
return new Joystick(input, dev, t);
}
}
dev->Release();
}
return 0;
}
static BOOL CALLBACK enumJoystick(LPCDIDEVICEINSTANCE devinst, LPVOID pvRef)
{
if ((devinst->dwDevType & 0xff) != DI8DEVCLASS_GAMECTRL)
return DIENUM_CONTINUE;
if (Joystick* joy = createJoystick((gxInput*)pvRef, devinst)) {
joysticks.push_back(joy);
}
return DIENUM_CONTINUE;
}
gxInput::gxInput(gxRuntime* rt, LPDIRECTINPUT8 di) : runtime(rt), dirInput(di)
{
keyboard = createKeyboard(this);
mouse = createMouse(this);
joysticks.clear();
dirInput->EnumDevices(DI8DEVCLASS_GAMECTRL, enumJoystick, this, DIEDFL_ATTACHEDONLY);
}
gxInput::~gxInput()
{
for (int k = 0; k < joysticks.size(); ++k)
delete joysticks[k];
joysticks.clear();
delete mouse;
delete keyboard;
dirInput->Release();
}
void gxInput::wm_keydown(int key)
{
if (keyboard)
keyboard->downEvent(key);
}
void gxInput::wm_keyup(int key)
{
if (keyboard)
keyboard->upEvent(key);
}
void gxInput::wm_mousedown(int key)
{
if (mouse)
mouse->downEvent(key);
}
void gxInput::wm_mouseup(int key)
{
if (mouse)
mouse->upEvent(key);
}
void gxInput::wm_mousemove(int x, int y)
{
if (mouse) {
mouse->axis_states[0] = x;
mouse->axis_states[1] = y;
}
}
void gxInput::wm_mousewheel(int dz)
{
if (mouse)
mouse->axis_states[2] += dz;
}
void gxInput::reset()
{
if (mouse)
mouse->reset();
if (keyboard)
keyboard->reset();
for (int k = 0; k < joysticks.size(); ++k)
joysticks[k]->reset();
}
bool gxInput::acquire()
{
bool m_ok = true, k_ok = true;
if (mouse)
m_ok = mouse->acquire();
if (keyboard)
k_ok = keyboard->acquire();
if (m_ok && k_ok)
return true;
if (k_ok)
keyboard->unacquire();
if (m_ok)
mouse->unacquire();
return false;
}
void gxInput::unacquire()
{
if (keyboard)
keyboard->unacquire();
if (mouse)
mouse->unacquire();
}
void gxInput::moveMouse(int x, int y)
{
if (!mouse)
return;
mouse->axis_states[0] = x;
mouse->axis_states[1] = y;
runtime->moveMouse(x, y);
}
gxDevice* gxInput::getMouse() const
{
return mouse;
}
gxDevice* gxInput::getKeyboard() const
{
return keyboard;
}
gxDevice* gxInput::getJoystick(int n) const
{
return n >= 0 && n < joysticks.size() ? joysticks[n] : 0;
}
int gxInput::getJoystickType(int n) const
{
return n >= 0 && n < joysticks.size() ? joysticks[n]->type : 0;
}
int gxInput::numJoysticks() const
{
return joysticks.size();
}
int gxInput::toAscii(int scan) const
{
switch (scan) {
case DIK_INSERT:
return ASC_INSERT;
case DIK_DELETE:
return ASC_DELETE;
case DIK_HOME:
return ASC_HOME;
case DIK_END:
return ASC_END;
case DIK_PGUP:
return ASC_PAGEUP;
case DIK_PGDN:
return ASC_PAGEDOWN;
case DIK_UP:
return ASC_UP;
case DIK_DOWN:
return ASC_DOWN;
case DIK_LEFT:
return ASC_LEFT;
case DIK_RIGHT:
return ASC_RIGHT;
}
scan &= 0x7f;
int virt = MapVirtualKey(scan, 1);
if (!virt)
return 0;
static unsigned char mat[256];
mat[VK_LSHIFT] = keyboard->keyDown(DIK_LSHIFT) ? 0x80 : 0;
mat[VK_RSHIFT] = keyboard->keyDown(DIK_RSHIFT) ? 0x80 : 0;
mat[VK_SHIFT] = mat[VK_LSHIFT] | mat[VK_RSHIFT];
mat[VK_LCONTROL] = keyboard->keyDown(DIK_LCONTROL) ? 0x80 : 0;
mat[VK_RCONTROL] = keyboard->keyDown(DIK_RCONTROL) ? 0x80 : 0;
mat[VK_CONTROL] = mat[VK_LCONTROL] | mat[VK_RCONTROL];
mat[VK_LMENU] = keyboard->keyDown(DIK_LMENU) ? 0x80 : 0;
mat[VK_RMENU] = keyboard->keyDown(DIK_RMENU) ? 0x80 : 0;
mat[VK_MENU] = mat[VK_LMENU] | mat[VK_RMENU];
WORD ch;
if (ToAscii(virt, scan, mat, &ch, 0) != 1)
return 0;
return ch & 255;
}