o cleanup
This commit is contained in:
261
tools/bsnes/ui_qt/input/device.cpp
Executable file
261
tools/bsnes/ui_qt/input/device.cpp
Executable file
@@ -0,0 +1,261 @@
|
||||
//===========
|
||||
//InputDevice
|
||||
//===========
|
||||
|
||||
InputDevice::InputDevice(SNES::Input::DeviceID i, bool p, const char *n) : InputGroup(n), id(i), port(p) {
|
||||
}
|
||||
|
||||
//======
|
||||
//Joypad
|
||||
//======
|
||||
|
||||
int16_t Joypad::state(unsigned index) const {
|
||||
if(config.input.allowInvalidInput == false) {
|
||||
//SNES D-pads have central pivot point, making up+down or left+right combinations impossible.
|
||||
//some software programs rely on this, and will crash if these combinations are allowed.
|
||||
if(index == SNES::Input::JoypadDown && up.state ) return 0;
|
||||
if(index == SNES::Input::JoypadRight && left.state) return 0;
|
||||
}
|
||||
|
||||
switch(index) {
|
||||
case SNES::Input::JoypadUp: return up.state;
|
||||
case SNES::Input::JoypadDown: return down.state;
|
||||
case SNES::Input::JoypadLeft: return left.state;
|
||||
case SNES::Input::JoypadRight: return right.state;
|
||||
case SNES::Input::JoypadA: return a.state;
|
||||
case SNES::Input::JoypadB: return b.state;
|
||||
case SNES::Input::JoypadX: return x.state;
|
||||
case SNES::Input::JoypadY: return y.state;
|
||||
case SNES::Input::JoypadL: return l.state;
|
||||
case SNES::Input::JoypadR: return r.state;
|
||||
case SNES::Input::JoypadSelect: return select.state;
|
||||
case SNES::Input::JoypadStart: return start.state;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Joypad::Joypad(SNES::Input::DeviceID id, bool port, const char *name,
|
||||
string &up_t, string &down_t, string &left_t, string &right_t, string &a_t, string &b_t,
|
||||
string &x_t, string &y_t, string &l_t, string &r_t, string &select_t, string &start_t
|
||||
) :
|
||||
InputDevice(id, port, name),
|
||||
up (InputObject::Button, "Up", up_t),
|
||||
down (InputObject::Button, "Down", down_t),
|
||||
left (InputObject::Button, "Left", left_t),
|
||||
right (InputObject::Button, "Right", right_t),
|
||||
a (InputObject::Button, "A", a_t),
|
||||
b (InputObject::Button, "B", b_t),
|
||||
x (InputObject::Button, "X", x_t),
|
||||
y (InputObject::Button, "Y", y_t),
|
||||
l (InputObject::Button, "L", l_t),
|
||||
r (InputObject::Button, "R", r_t),
|
||||
select(InputObject::Button, "Select", select_t),
|
||||
start (InputObject::Button, "Start", start_t) {
|
||||
attach(up); attach(down); attach(left); attach(right); attach(a); attach(b);
|
||||
attach(x); attach(y); attach(l); attach(r); attach(select); attach(start);
|
||||
}
|
||||
|
||||
//=====
|
||||
//Mouse
|
||||
//=====
|
||||
|
||||
int16_t Mouse::state(unsigned index) const {
|
||||
switch(index) {
|
||||
case SNES::Input::MouseX: return x.state;
|
||||
case SNES::Input::MouseY: return y.state;
|
||||
case SNES::Input::MouseLeft: return left.state;
|
||||
case SNES::Input::MouseRight: return right.state;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Mouse::Mouse(SNES::Input::DeviceID id, bool port, const char *name,
|
||||
string &x_t, string &y_t, string &left_t, string &right_t
|
||||
) :
|
||||
InputDevice(id, port, name),
|
||||
x (InputObject::Axis, "X-axis", x_t),
|
||||
y (InputObject::Axis, "Y-axis", y_t),
|
||||
left (InputObject::Button, "Left button", left_t),
|
||||
right(InputObject::Button, "Right button", right_t) {
|
||||
attach(x); attach(y); attach(left); attach(right);
|
||||
}
|
||||
|
||||
//==========
|
||||
//SuperScope
|
||||
//==========
|
||||
|
||||
int16_t SuperScope::state(unsigned index) const {
|
||||
switch(index) {
|
||||
case SNES::Input::SuperScopeX: return x.state;
|
||||
case SNES::Input::SuperScopeY: return y.state;
|
||||
case SNES::Input::SuperScopeTrigger: return trigger.state;
|
||||
case SNES::Input::SuperScopeCursor: return cursor.state;
|
||||
case SNES::Input::SuperScopeTurbo: return turbo.state;
|
||||
case SNES::Input::SuperScopePause: return pause.state;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SuperScope::SuperScope(SNES::Input::DeviceID id, bool port, const char *name,
|
||||
string &x_t, string &y_t, string &trigger_t, string &cursor_t, string &turbo_t, string &pause_t
|
||||
) :
|
||||
InputDevice(id, port, name),
|
||||
x (InputObject::Axis, "X-axis", x_t),
|
||||
y (InputObject::Axis, "Y-axis", y_t),
|
||||
trigger(InputObject::Button, "Trigger", trigger_t),
|
||||
cursor (InputObject::Button, "Cursor", cursor_t),
|
||||
turbo (InputObject::Button, "Turbo", turbo_t),
|
||||
pause (InputObject::Button, "Pause", pause_t) {
|
||||
attach(x); attach(y); attach(trigger); attach(cursor); attach(turbo); attach(pause);
|
||||
}
|
||||
|
||||
//=========
|
||||
//Justifier
|
||||
//=========
|
||||
|
||||
int16_t Justifier::state(unsigned index) const {
|
||||
switch(index) {
|
||||
case SNES::Input::JustifierX: return x.state;
|
||||
case SNES::Input::JustifierY: return y.state;
|
||||
case SNES::Input::JustifierTrigger: return trigger.state;
|
||||
case SNES::Input::JustifierStart: return start.state;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Justifier::Justifier(SNES::Input::DeviceID id, bool port, const char *name,
|
||||
string &x_t, string &y_t, string &trigger_t, string &start_t
|
||||
) :
|
||||
InputDevice(id, port, name),
|
||||
x (InputObject::Axis, "X-axis", x_t),
|
||||
y (InputObject::Axis, "Y-axis", y_t),
|
||||
trigger(InputObject::Button, "Trigger", trigger_t),
|
||||
start (InputObject::Button, "Start", start_t) {
|
||||
attach(x); attach(y); attach(trigger); attach(start);
|
||||
}
|
||||
|
||||
//===============
|
||||
//InputDevicePool
|
||||
//===============
|
||||
|
||||
void InputDevicePool::attach(InputDevice &device) {
|
||||
list.add(&device);
|
||||
}
|
||||
|
||||
void InputDevicePool::bind() {
|
||||
for(unsigned i = 0; i < list.size(); i++) list[i]->bind();
|
||||
}
|
||||
|
||||
void InputDevicePool::clear() {
|
||||
for(unsigned i = 0; i < list.size(); i++) list[i]->clear();
|
||||
}
|
||||
|
||||
void InputDevicePool::poll(const int16_t *table) {
|
||||
for(unsigned i = 0; i < list.size(); i++) list[i]->poll(table);
|
||||
}
|
||||
|
||||
InputDevice* InputDevicePool::find(SNES::Input::DeviceID id) {
|
||||
for(unsigned i = 0; i < list.size(); i++) {
|
||||
if(list[i]->id == id) return list[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
InputDevicePool::InputDevicePool() : list(*this) {
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
Joypad joypad1(SNES::Input::DeviceIDJoypad1, InputDevice::Port1, "Joypad",
|
||||
config.input.joypad1.up, config.input.joypad1.down, config.input.joypad1.left, config.input.joypad1.right,
|
||||
config.input.joypad1.a, config.input.joypad1.b, config.input.joypad1.x, config.input.joypad1.y,
|
||||
config.input.joypad1.l, config.input.joypad1.r, config.input.joypad1.select, config.input.joypad1.start);
|
||||
|
||||
Joypad joypad2(SNES::Input::DeviceIDJoypad2, InputDevice::Port2, "Joypad",
|
||||
config.input.joypad2.up, config.input.joypad2.down, config.input.joypad2.left, config.input.joypad2.right,
|
||||
config.input.joypad2.a, config.input.joypad2.b, config.input.joypad2.x, config.input.joypad2.y,
|
||||
config.input.joypad2.l, config.input.joypad2.r, config.input.joypad2.select, config.input.joypad2.start);
|
||||
|
||||
Joypad multitap1a(SNES::Input::DeviceIDMultitap1A, InputDevice::Port1, "Multitap - Port 1",
|
||||
config.input.multitap1a.up, config.input.multitap1a.down, config.input.multitap1a.left, config.input.multitap1a.right,
|
||||
config.input.multitap1a.a, config.input.multitap1a.b, config.input.multitap1a.x, config.input.multitap1a.y,
|
||||
config.input.multitap1a.l, config.input.multitap1a.r, config.input.multitap1a.select, config.input.multitap1a.start);
|
||||
|
||||
Joypad multitap1b(SNES::Input::DeviceIDMultitap1B, InputDevice::Port1, "Multitap - Port 2",
|
||||
config.input.multitap1b.up, config.input.multitap1b.down, config.input.multitap1b.left, config.input.multitap1b.right,
|
||||
config.input.multitap1b.a, config.input.multitap1b.b, config.input.multitap1b.x, config.input.multitap1b.y,
|
||||
config.input.multitap1b.l, config.input.multitap1b.r, config.input.multitap1b.select, config.input.multitap1b.start);
|
||||
|
||||
Joypad multitap1c(SNES::Input::DeviceIDMultitap1C, InputDevice::Port1, "Multitap - Port 3",
|
||||
config.input.multitap1c.up, config.input.multitap1c.down, config.input.multitap1c.left, config.input.multitap1c.right,
|
||||
config.input.multitap1c.a, config.input.multitap1c.b, config.input.multitap1c.x, config.input.multitap1c.y,
|
||||
config.input.multitap1c.l, config.input.multitap1c.r, config.input.multitap1c.select, config.input.multitap1c.start);
|
||||
|
||||
Joypad multitap1d(SNES::Input::DeviceIDMultitap1D, InputDevice::Port1, "Multitap - Port 4",
|
||||
config.input.multitap1d.up, config.input.multitap1d.down, config.input.multitap1d.left, config.input.multitap1d.right,
|
||||
config.input.multitap1d.a, config.input.multitap1d.b, config.input.multitap1d.x, config.input.multitap1d.y,
|
||||
config.input.multitap1d.l, config.input.multitap1d.r, config.input.multitap1d.select, config.input.multitap1d.start);
|
||||
|
||||
Joypad multitap2a(SNES::Input::DeviceIDMultitap2A, InputDevice::Port2, "Multitap - Port 1",
|
||||
config.input.multitap2a.up, config.input.multitap2a.down, config.input.multitap2a.left, config.input.multitap2a.right,
|
||||
config.input.multitap2a.a, config.input.multitap2a.b, config.input.multitap2a.x, config.input.multitap2a.y,
|
||||
config.input.multitap2a.l, config.input.multitap2a.r, config.input.multitap2a.select, config.input.multitap2a.start);
|
||||
|
||||
Joypad multitap2b(SNES::Input::DeviceIDMultitap2B, InputDevice::Port2, "Multitap - Port 2",
|
||||
config.input.multitap2b.up, config.input.multitap2b.down, config.input.multitap2b.left, config.input.multitap2b.right,
|
||||
config.input.multitap2b.a, config.input.multitap2b.b, config.input.multitap2b.x, config.input.multitap2b.y,
|
||||
config.input.multitap2b.l, config.input.multitap2b.r, config.input.multitap2b.select, config.input.multitap2b.start);
|
||||
|
||||
Joypad multitap2c(SNES::Input::DeviceIDMultitap2C, InputDevice::Port2, "Multitap - Port 3",
|
||||
config.input.multitap2c.up, config.input.multitap2c.down, config.input.multitap2c.left, config.input.multitap2c.right,
|
||||
config.input.multitap2c.a, config.input.multitap2c.b, config.input.multitap2c.x, config.input.multitap2c.y,
|
||||
config.input.multitap2c.l, config.input.multitap2c.r, config.input.multitap2c.select, config.input.multitap2c.start);
|
||||
|
||||
Joypad multitap2d(SNES::Input::DeviceIDMultitap2D, InputDevice::Port2, "Multitap - Port 4",
|
||||
config.input.multitap2d.up, config.input.multitap2d.down, config.input.multitap2d.left, config.input.multitap2d.right,
|
||||
config.input.multitap2d.a, config.input.multitap2d.b, config.input.multitap2d.x, config.input.multitap2d.y,
|
||||
config.input.multitap2d.l, config.input.multitap2d.r, config.input.multitap2d.select, config.input.multitap2d.start);
|
||||
|
||||
Mouse mouse1(SNES::Input::DeviceIDMouse1, InputDevice::Port1, "Mouse",
|
||||
config.input.mouse1.x, config.input.mouse1.y, config.input.mouse1.left, config.input.mouse1.right);
|
||||
|
||||
Mouse mouse2(SNES::Input::DeviceIDMouse2, InputDevice::Port2, "Mouse",
|
||||
config.input.mouse2.x, config.input.mouse2.y, config.input.mouse2.left, config.input.mouse2.right);
|
||||
|
||||
SuperScope superscope(SNES::Input::DeviceIDSuperScope, InputDevice::Port2, "Super Scope",
|
||||
config.input.superscope.x, config.input.superscope.y,
|
||||
config.input.superscope.trigger, config.input.superscope.cursor,
|
||||
config.input.superscope.turbo, config.input.superscope.pause);
|
||||
|
||||
Justifier justifier1(SNES::Input::DeviceIDJustifier1, InputDevice::Port2, "Justifier 1",
|
||||
config.input.justifier1.x, config.input.justifier1.y,
|
||||
config.input.justifier1.trigger, config.input.justifier1.start);
|
||||
|
||||
Justifier justifier2(SNES::Input::DeviceIDJustifier2, InputDevice::Port2, "Justifier 2",
|
||||
config.input.justifier2.x, config.input.justifier2.y,
|
||||
config.input.justifier2.trigger, config.input.justifier2.start);
|
||||
|
||||
InputSnesDevicePool inputPool;
|
||||
|
||||
InputSnesDevicePool::InputSnesDevicePool() {
|
||||
attach(joypad1);
|
||||
attach(joypad2);
|
||||
attach(multitap1a);
|
||||
attach(multitap1b);
|
||||
attach(multitap1c);
|
||||
attach(multitap1d);
|
||||
attach(multitap2a);
|
||||
attach(multitap2b);
|
||||
attach(multitap2c);
|
||||
attach(multitap2d);
|
||||
attach(mouse1);
|
||||
attach(mouse2);
|
||||
attach(superscope);
|
||||
attach(justifier1);
|
||||
attach(justifier2);
|
||||
}
|
||||
73
tools/bsnes/ui_qt/input/device.hpp
Executable file
73
tools/bsnes/ui_qt/input/device.hpp
Executable file
@@ -0,0 +1,73 @@
|
||||
struct InputDevice : InputGroup {
|
||||
SNES::Input::DeviceID id;
|
||||
enum Port { Port1, Port2 };
|
||||
const bool port;
|
||||
|
||||
InputDevice(SNES::Input::DeviceID i, bool p, const char *n);
|
||||
};
|
||||
|
||||
struct Joypad : InputDevice {
|
||||
InputObject up, down, left, right, a, b, x, y, l, r, select, start;
|
||||
|
||||
int16_t state(unsigned index) const;
|
||||
Joypad(SNES::Input::DeviceID id, bool port, const char *name,
|
||||
string&, string&, string&, string&, string&, string&,
|
||||
string&, string&, string&, string&, string&, string&);
|
||||
};
|
||||
|
||||
struct Mouse : InputDevice {
|
||||
InputObject x, y, left, right;
|
||||
|
||||
int16_t state(unsigned index) const;
|
||||
Mouse(SNES::Input::DeviceID id, bool port, const char *name,
|
||||
string&, string&, string&, string&);
|
||||
};
|
||||
|
||||
struct SuperScope : InputDevice {
|
||||
InputObject x, y, trigger, cursor, turbo, pause;
|
||||
|
||||
int16_t state(unsigned index) const;
|
||||
SuperScope(SNES::Input::DeviceID id, bool port, const char *name,
|
||||
string&, string&, string&, string&, string&, string&);
|
||||
};
|
||||
|
||||
struct Justifier : InputDevice {
|
||||
InputObject x, y, trigger, start;
|
||||
|
||||
int16_t state(unsigned index) const;
|
||||
Justifier(SNES::Input::DeviceID id, bool port, const char *name,
|
||||
string&, string&, string&, string&);
|
||||
};
|
||||
|
||||
struct InputDevicePool : public array<InputDevice*> {
|
||||
void attach(InputDevice &device);
|
||||
void bind();
|
||||
void clear();
|
||||
void poll(const int16_t *table);
|
||||
InputDevice* find(SNES::Input::DeviceID id);
|
||||
InputDevicePool();
|
||||
|
||||
private:
|
||||
array<InputDevice*> &list;
|
||||
};
|
||||
|
||||
struct InputSnesDevicePool : public InputDevicePool {
|
||||
InputSnesDevicePool();
|
||||
};
|
||||
|
||||
extern Joypad joypad1;
|
||||
extern Joypad joypad2;
|
||||
extern Joypad multitap1a;
|
||||
extern Joypad multitap1b;
|
||||
extern Joypad multitap1c;
|
||||
extern Joypad multitap1d;
|
||||
extern Joypad multitap2a;
|
||||
extern Joypad multitap2b;
|
||||
extern Joypad multitap2c;
|
||||
extern Joypad multitap2d;
|
||||
extern Mouse mouse1;
|
||||
extern Mouse mouse2;
|
||||
extern SuperScope superscope;
|
||||
extern Justifier justifier1;
|
||||
extern Justifier justifier2;
|
||||
extern InputSnesDevicePool inputPool;
|
||||
269
tools/bsnes/ui_qt/input/input.cpp
Executable file
269
tools/bsnes/ui_qt/input/input.cpp
Executable file
@@ -0,0 +1,269 @@
|
||||
#include "device.cpp"
|
||||
#include "userinterface.cpp"
|
||||
|
||||
//=========
|
||||
//InputCode
|
||||
//=========
|
||||
|
||||
InputCode::type_t InputCode::type(uint16_t code) {
|
||||
for(unsigned i = 0; i < keyboard<>::count; i++) {
|
||||
unsigned index = keyboard<>::index(i, keyboard<>::none);
|
||||
if(code >= index && code < index + keyboard<>::length) return KeyboardButton;
|
||||
}
|
||||
|
||||
for(unsigned i = 0; i < mouse<>::count; i++) {
|
||||
unsigned index = mouse<>::index(i, mouse<>::none);
|
||||
if(code == index + mouse<>::x) return MouseAxis;
|
||||
if(code == index + mouse<>::y) return MouseAxis;
|
||||
if(code == index + mouse<>::z) return MouseAxis;
|
||||
|
||||
index = mouse<>::index(i, mouse<>::button);
|
||||
if(code >= index && code < index + mouse<>::buttons) return MouseButton;
|
||||
}
|
||||
|
||||
for(unsigned i = 0; i < joypad<>::count; i++) {
|
||||
unsigned index;
|
||||
|
||||
index = joypad<>::index(i, joypad<>::hat);
|
||||
if(code >= index && code < index + joypad<>::hats) return JoypadHat;
|
||||
|
||||
index = joypad<>::index(i, joypad<>::axis);
|
||||
if(code >= index && code < index + joypad<>::axes) return JoypadAxis;
|
||||
|
||||
index = joypad<>::index(i, joypad<>::button);
|
||||
if(code >= index && code < index + joypad<>::buttons) return JoypadButton;
|
||||
}
|
||||
|
||||
return Unknown;
|
||||
}
|
||||
|
||||
InputCode::axistype_t InputCode::axisType(uint16_t code) {
|
||||
for(unsigned i = 0; i < joypad<>::count; i++) {
|
||||
unsigned index = joypad<>::index(i, joypad<>::axis);
|
||||
if(code >= index && code < index + joypad<>::axes) {
|
||||
return (InputCode::axistype_t)inputManager.axisType(i, code - index);
|
||||
}
|
||||
}
|
||||
return InvalidAxis;
|
||||
}
|
||||
|
||||
//finds what mouse# is associated with code, returns -1 if not a mouse code
|
||||
int InputCode::mouseNumber(uint16_t code) {
|
||||
for(unsigned i = 0; i < mouse<>::count; i++) {
|
||||
unsigned index = mouse<>::index(i, mouse<>::none);
|
||||
if(code >= index && code < index + mouse<>::length) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//finds what joypad# is associated with code, returns -1 if not a joypad code
|
||||
int InputCode::joypadNumber(uint16_t code) {
|
||||
for(unsigned i = 0; i < joypad<>::count; i++) {
|
||||
unsigned index = joypad<>::index(i, joypad<>::none);
|
||||
if(code >= index && code < index + joypad<>::length) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//============
|
||||
//InputManager
|
||||
//============
|
||||
|
||||
void InputManager::bind() {
|
||||
inputPool.bind();
|
||||
inputUiPool.bind();
|
||||
}
|
||||
|
||||
void InputManager::poll() {
|
||||
if(config.input.focusPolicy == Configuration::Input::FocusPolicyIgnoreInput
|
||||
&& winMain->window->isActiveWindow() == false) {
|
||||
inputPool.clear();
|
||||
} else {
|
||||
inputPool.poll(stateTable[activeState]);
|
||||
}
|
||||
}
|
||||
|
||||
void InputManager::clear() {
|
||||
inputPool.clear();
|
||||
}
|
||||
|
||||
void InputManager::flush() {
|
||||
for(unsigned i = 0; i < nall::input_limit; i++) {
|
||||
stateTable[0][i] = 0;
|
||||
stateTable[1][i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int16_t InputManager::state(uint16_t code) const {
|
||||
return stateTable[ activeState][code];
|
||||
}
|
||||
|
||||
int16_t InputManager::lastState(uint16_t code) const {
|
||||
return stateTable[!activeState][code];
|
||||
}
|
||||
|
||||
int16_t InputManager::getStatus(unsigned deviceid, unsigned id) const {
|
||||
InputDevice *device = inputPool.find((SNES::Input::DeviceID)deviceid);
|
||||
if(device) return device->state(id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void InputManager::refresh() {
|
||||
bool last = activeState;
|
||||
activeState = !activeState;
|
||||
bool next = activeState;
|
||||
|
||||
input.poll(stateTable[next]);
|
||||
for(unsigned i = 0; i < nall::input_limit; i++) {
|
||||
//alert via callback whenever input state changes for any ID ...
|
||||
if(onInput && stateTable[last][i] != stateTable[next][i]) onInput(i);
|
||||
}
|
||||
}
|
||||
|
||||
void InputManager::calibrate(unsigned joy) {
|
||||
unsigned index = joypad<>::index(joy, joypad<>::none);
|
||||
|
||||
for(unsigned axis = 0; axis < joypad<>::axes; axis++) {
|
||||
int16_t value = state(index + joypad<>::axis + axis);
|
||||
pad[joy].axis[axis] = (value >= -16384 && value <= +16384) ? InputCode::Stick : InputCode::Trigger;
|
||||
}
|
||||
|
||||
pad[joy].calibrated = true;
|
||||
}
|
||||
|
||||
bool InputManager::calibrated(unsigned joy) const {
|
||||
return pad[joy].calibrated;
|
||||
}
|
||||
|
||||
InputCode::axistype_t InputManager::axisType(unsigned joy, unsigned axis) const {
|
||||
return pad[joy].axis[axis];
|
||||
}
|
||||
|
||||
InputManager::InputManager() {
|
||||
activeState = 0;
|
||||
flush();
|
||||
|
||||
for(unsigned i = 0; i < joypad<>::count; i++) {
|
||||
pad[i].calibrated = false;
|
||||
for(unsigned n = 0; n < joypad<>::axes; n++) pad[i].axis[n] = InputCode::InvalidAxis;
|
||||
}
|
||||
}
|
||||
|
||||
//===========
|
||||
//InputObject
|
||||
//===========
|
||||
|
||||
void InputObject::bind() {
|
||||
lstring part;
|
||||
part.split("::", id);
|
||||
|
||||
code = nall::input_find((const char*)part[0]);
|
||||
codetype = InputCode::type(code);
|
||||
|
||||
modifier = None;
|
||||
if(part.size() > 1) {
|
||||
if(part[1] == "up" ) modifier = Up;
|
||||
if(part[1] == "down" ) modifier = Down;
|
||||
if(part[1] == "left" ) modifier = Left;
|
||||
if(part[1] == "right" ) modifier = Right;
|
||||
if(part[1] == "lo" ) modifier = Lo;
|
||||
if(part[1] == "hi" ) modifier = Hi;
|
||||
if(part[1] == "trigger") modifier = Trigger;
|
||||
}
|
||||
|
||||
if(code == nall::input_none) id = "none";
|
||||
}
|
||||
|
||||
void InputObject::bind(uint16_t newCode) {
|
||||
code = newCode;
|
||||
codetype = InputCode::type(code);
|
||||
|
||||
id = nall::input_find(newCode);
|
||||
modifier = None;
|
||||
|
||||
if(type == Button && codetype == InputCode::JoypadHat) {
|
||||
switch(inputManager.state(code)) {
|
||||
case joypad<>::hat_up: id << "::up"; modifier = Up; break;
|
||||
case joypad<>::hat_down: id << "::down"; modifier = Down; break;
|
||||
case joypad<>::hat_left: id << "::left"; modifier = Left; break;
|
||||
case joypad<>::hat_right: id << "::right"; modifier = Right; break;
|
||||
}
|
||||
} else if(type == Button && codetype == InputCode::JoypadAxis) {
|
||||
InputCode::axistype_t type = InputCode::axisType(code);
|
||||
int16_t state = inputManager.state(code);
|
||||
|
||||
if(type == InputCode::Stick) {
|
||||
if(state < 0) {
|
||||
id << "::lo";
|
||||
modifier = Lo;
|
||||
} else {
|
||||
id << "::hi";
|
||||
modifier = Hi;
|
||||
}
|
||||
} else if(type == InputCode::Trigger) {
|
||||
id << "::trigger";
|
||||
modifier = Trigger;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InputObject::poll(int16_t newState) {
|
||||
if(type == Button && codetype == InputCode::JoypadHat) {
|
||||
//map 4-way hat input to button state
|
||||
state = (modifier == Up && (newState & joypad<>::hat_up ))
|
||||
|| (modifier == Down && (newState & joypad<>::hat_down ))
|
||||
|| (modifier == Left && (newState & joypad<>::hat_left ))
|
||||
|| (modifier == Right && (newState & joypad<>::hat_right));
|
||||
} else if(type == Button && codetype == InputCode::JoypadAxis) {
|
||||
//convert analog input to button state
|
||||
state = (modifier == Lo && newState < -16384)
|
||||
|| (modifier == Hi && newState > +16384)
|
||||
|| (modifier == Trigger && newState < 0);
|
||||
} else if(codetype == InputCode::MouseAxis && !input.acquired()) {
|
||||
//mouse must be acquired (locked to window) to move axes
|
||||
state = 0;
|
||||
} else if(0 && codetype == InputCode::MouseButton && !input.acquired()) {
|
||||
//same for buttons
|
||||
//note: disabled for now ... requiring exclusive access makes it much more difficult
|
||||
//to utilize mouse buttons for eg SNES joypad input.
|
||||
state = 0;
|
||||
} else if(codetype == InputCode::JoypadAxis) {
|
||||
//joypad axis range = -32768 to +32767, scale to -8 to +7 to roughly match mouse delta
|
||||
//todo: scale mouse up instead of joypad down? (would require mouse DPI / resolution)
|
||||
state = newState / 4096;
|
||||
} else {
|
||||
state = newState;
|
||||
}
|
||||
}
|
||||
|
||||
InputObject::InputObject(InputObject::type_t t, const char *n, string &s) : parent(0), type(t), name(n), id(s) {
|
||||
}
|
||||
|
||||
//==========
|
||||
//InputGroup
|
||||
//==========
|
||||
|
||||
void InputGroup::attach(InputObject &object) {
|
||||
list.add(&object);
|
||||
object.parent = this;
|
||||
}
|
||||
|
||||
void InputGroup::bind() {
|
||||
for(unsigned i = 0; i < list.size(); i++) list[i]->bind();
|
||||
}
|
||||
|
||||
void InputGroup::clear() {
|
||||
for(unsigned i = 0; i < list.size(); i++) list[i]->state = 0;
|
||||
}
|
||||
|
||||
void InputGroup::poll(const int16_t *table) {
|
||||
for(unsigned i = 0; i < list.size(); i++) list[i]->poll(table[list[i]->code]);
|
||||
}
|
||||
|
||||
int16_t InputGroup::state(unsigned index) const {
|
||||
if(index < list.size()) return list[index]->state;
|
||||
return 0;
|
||||
}
|
||||
|
||||
InputGroup::InputGroup(const char *n) : list(*this), name(n) {
|
||||
}
|
||||
88
tools/bsnes/ui_qt/input/input.hpp
Executable file
88
tools/bsnes/ui_qt/input/input.hpp
Executable file
@@ -0,0 +1,88 @@
|
||||
struct InputCode {
|
||||
enum type_t {
|
||||
KeyboardButton,
|
||||
MouseAxis,
|
||||
MouseButton,
|
||||
JoypadHat,
|
||||
JoypadAxis,
|
||||
JoypadButton,
|
||||
Unknown,
|
||||
};
|
||||
enum axistype_t {
|
||||
Stick, //bi-directional, centered analog stick (min = -32768, inactive = 0, max = +32767)
|
||||
Trigger, //uni-directional, pressure-sensitive analog trigger button (min = -32768, inactive = max = +32767)
|
||||
InvalidAxis, //not a joypad axis code, or said joypad is not calibrated
|
||||
};
|
||||
static type_t type(uint16_t code);
|
||||
static axistype_t axisType(uint16_t code);
|
||||
static int mouseNumber(uint16_t code);
|
||||
static int joypadNumber(uint16_t code);
|
||||
};
|
||||
|
||||
class InputManager {
|
||||
public:
|
||||
void bind();
|
||||
void poll();
|
||||
void clear();
|
||||
void flush();
|
||||
|
||||
int16_t state(uint16_t code) const;
|
||||
int16_t lastState(uint16_t code) const;
|
||||
int16_t getStatus(unsigned deviceid, unsigned id) const;
|
||||
|
||||
void refresh();
|
||||
void calibrate(unsigned joypad);
|
||||
bool calibrated(unsigned joypad) const;
|
||||
InputCode::axistype_t axisType(unsigned joypad, unsigned axis) const;
|
||||
function<void (uint16_t)> onInput;
|
||||
|
||||
InputManager();
|
||||
|
||||
private:
|
||||
bool activeState;
|
||||
int16_t stateTable[2][nall::input_limit];
|
||||
|
||||
//joypad axis calibration data
|
||||
struct Pad {
|
||||
bool calibrated;
|
||||
InputCode::axistype_t axis[joypad<>::axes];
|
||||
} pad[joypad<>::count];
|
||||
} inputManager;
|
||||
|
||||
struct InputGroup;
|
||||
|
||||
struct InputObject {
|
||||
InputGroup *parent;
|
||||
enum type_t { Button, Axis };
|
||||
enum modifier_t { None, Up, Down, Left, Right, Lo, Hi, Trigger };
|
||||
|
||||
type_t type; //type of input this object is mapped to
|
||||
const char *name; //plain-text name ("Up", "Down", ... "Start")
|
||||
string &id; //config-item reference ("joypad1.start") name ("joypad00.button00")
|
||||
uint16_t code; //nall::input code ID
|
||||
InputCode::type_t codetype; //hardware button / axis type
|
||||
modifier_t modifier; //hardware specialization (joypad-axis "::lo", "::hi", etc)
|
||||
int16_t state; //code state as of last inputManager.poll()
|
||||
|
||||
void bind();
|
||||
void bind(uint16_t code);
|
||||
void poll(int16_t state);
|
||||
InputObject(type_t t, const char *n, string &s);
|
||||
};
|
||||
|
||||
struct InputGroup : public array<InputObject*> {
|
||||
const char *name;
|
||||
|
||||
void attach(InputObject &object);
|
||||
void bind();
|
||||
void clear();
|
||||
void poll(const int16_t *table);
|
||||
virtual int16_t state(unsigned index) const;
|
||||
InputGroup(const char *n);
|
||||
|
||||
private:
|
||||
array<InputObject*> &list;
|
||||
};
|
||||
|
||||
#include "device.hpp"
|
||||
#include "userinterface.hpp"
|
||||
56
tools/bsnes/ui_qt/input/userinterface.cpp
Executable file
56
tools/bsnes/ui_qt/input/userinterface.cpp
Executable file
@@ -0,0 +1,56 @@
|
||||
//==============
|
||||
//InputGroupPool
|
||||
//==============
|
||||
|
||||
void InputGroupPool::attach(InputGroup &group) {
|
||||
list.add(&group);
|
||||
}
|
||||
|
||||
void InputGroupPool::bind() {
|
||||
for(unsigned i = 0; i < list.size(); i++) list[i]->bind();
|
||||
}
|
||||
|
||||
void InputGroupPool::clear() {
|
||||
for(unsigned i = 0; i < list.size(); i++) list[i]->clear();
|
||||
}
|
||||
|
||||
void InputGroupPool::poll(const int16_t *table) {
|
||||
for(unsigned i = 0; i < list.size(); i++) list[i]->poll(table);
|
||||
}
|
||||
|
||||
InputGroupPool::InputGroupPool() : list(*this) {
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
InputUiGeneral inputUiGeneral;
|
||||
InputUiPool inputUiPool;
|
||||
|
||||
InputUiGeneral::InputUiGeneral() : InputGroup("General"),
|
||||
loadCartridge(InputObject::Button, "Load cartridge", config.input.uiGeneral.loadCartridge),
|
||||
pauseEmulation(InputObject::Button, "Pause emulation", config.input.uiGeneral.pauseEmulation),
|
||||
resetSystem(InputObject::Button, "Reset system", config.input.uiGeneral.resetSystem),
|
||||
powerCycleSystem(InputObject::Button, "Power cycle system", config.input.uiGeneral.powerCycleSystem),
|
||||
lowerSpeed(InputObject::Button, "Decrease emulation speed", config.input.uiGeneral.lowerSpeed),
|
||||
raiseSpeed(InputObject::Button, "Increase emulation speed", config.input.uiGeneral.raiseSpeed),
|
||||
toggleCheatSystem(InputObject::Button, "Toggle cheat system on or off", config.input.uiGeneral.toggleCheatSystem),
|
||||
toggleFullscreen(InputObject::Button, "Toggle fullscreen mode", config.input.uiGeneral.toggleFullscreen),
|
||||
toggleMenu(InputObject::Button, "Toggle menubar", config.input.uiGeneral.toggleMenu),
|
||||
toggleStatus(InputObject::Button, "Toggle statusbar", config.input.uiGeneral.toggleStatus),
|
||||
exitEmulator(InputObject::Button, "Exit emulator", config.input.uiGeneral.exitEmulator) {
|
||||
attach(loadCartridge);
|
||||
attach(pauseEmulation);
|
||||
attach(resetSystem);
|
||||
attach(powerCycleSystem);
|
||||
attach(lowerSpeed);
|
||||
attach(raiseSpeed);
|
||||
attach(toggleCheatSystem);
|
||||
attach(toggleFullscreen);
|
||||
attach(toggleMenu);
|
||||
attach(toggleStatus);
|
||||
attach(exitEmulator);
|
||||
}
|
||||
|
||||
InputUiPool::InputUiPool() {
|
||||
attach(inputUiGeneral);
|
||||
}
|
||||
33
tools/bsnes/ui_qt/input/userinterface.hpp
Executable file
33
tools/bsnes/ui_qt/input/userinterface.hpp
Executable file
@@ -0,0 +1,33 @@
|
||||
struct InputUiGeneral : public InputGroup {
|
||||
InputObject loadCartridge;
|
||||
InputObject pauseEmulation;
|
||||
InputObject resetSystem;
|
||||
InputObject powerCycleSystem;
|
||||
InputObject lowerSpeed;
|
||||
InputObject raiseSpeed;
|
||||
InputObject toggleCheatSystem;
|
||||
InputObject toggleFullscreen;
|
||||
InputObject toggleMenu;
|
||||
InputObject toggleStatus;
|
||||
InputObject exitEmulator;
|
||||
|
||||
InputUiGeneral();
|
||||
};
|
||||
|
||||
struct InputGroupPool : public array<InputGroup*> {
|
||||
void attach(InputGroup &group);
|
||||
void bind();
|
||||
void clear();
|
||||
void poll(const int16_t *table);
|
||||
InputGroupPool();
|
||||
|
||||
private:
|
||||
array<InputGroup*> &list;
|
||||
};
|
||||
|
||||
struct InputUiPool : public InputGroupPool {
|
||||
InputUiPool();
|
||||
};
|
||||
|
||||
extern InputUiGeneral inputUiGeneral;
|
||||
extern InputUiPool inputUiPool;
|
||||
Reference in New Issue
Block a user