lsnes/ui/input/input.cpp
2013-05-03 17:47:34 +03:00

212 lines
5.8 KiB
C++
Executable file

#include "../base.hpp"
#include "nes.cpp"
#include "snes.cpp"
#include "gameboy.cpp"
#include "user-interface.cpp"
InputManager *inputManager = 0;
void AbstractInput::attach(const string &primaryName, const string &secondaryName, const string &tertiaryName) {
string name = { primaryName, "::", secondaryName, "::", tertiaryName, "::", this->name };
name.replace(" ", "");
inputManager->config.attach(mapping, name);
}
void AbstractInput::bind() {
if(mapping == "") type = Type::Button, mapping = "None";
if(mapping.endswith(".Up")) type = Type::HatUp;
else if(mapping.endswith(".Down")) type = Type::HatDown;
else if(mapping.endswith(".Left")) type = Type::HatLeft;
else if(mapping.endswith(".Right")) type = Type::HatRight;
else if(mapping.endswith(".Lo")) type = Type::AxisLo;
else if(mapping.endswith(".Hi")) type = Type::AxisHi;
else if(mapping.beginswith("JP") && mapping.position("Axis")) type = Type::Axis;
else if(mapping.beginswith("MS") && mapping.endswith("axis")) type = Type::MouseAxis;
else if(mapping.beginswith("MS")) type = Type::MouseButton;
else type = Type::Button;
string decode = mapping;
if(auto position = decode.position(".")) decode[position()] = 0;
scancode = Scancode::decode(decode);
}
int16_t AbstractInput::poll() {
if(config->input.focusPolicy == 1 && mainWindow->focused() == false) return 0;
return inputManager->scancode[inputManager->activeScancode][scancode];
}
//
bool AnalogInput::bind(int16_t scancode, int16_t value) {
string encode = Scancode::encode(scancode);
Type type = Type::Button;
if(scancode == Scancode::None) goto bind;
if(Mouse::isAnyAxis(scancode)) { type = Type::MouseAxis; goto bind; }
if(Joypad::isAnyAxis(scancode)) { type = Type::Axis; goto bind; }
return false;
bind:
mapping = encode;
this->scancode = scancode;
this->type = Type::Axis;
return true;
}
int16_t AnalogInput::poll() {
int16_t value = AbstractInput::poll();
switch(type) {
case Type::MouseAxis: return input.acquired() ? value : 0;
case Type::Axis: return value;
}
return 0;
}
//
bool DigitalInput::bind(int16_t scancode, int16_t value) {
string encode = Scancode::encode(scancode);
Type type = Type::Button;
if(scancode == Scancode::None) goto bind;
if(Keyboard::isAnyKey(scancode) || Keyboard::isAnyModifier(scancode) || Joypad::isAnyButton(scancode)) {
if(value == 0) return false;
type = Type::Button;
goto bind;
}
if(Mouse::isAnyButton(scancode)) {
if(value == 0) return false;
type = Type::MouseButton;
goto bind;
}
if(Joypad::isAnyHat(scancode)) {
if(value & Joypad::HatUp ) { type = Type::HatUp; encode.append(".Up" ); goto bind; }
if(value & Joypad::HatDown ) { type = Type::HatDown; encode.append(".Down" ); goto bind; }
if(value & Joypad::HatLeft ) { type = Type::HatLeft; encode.append(".Left" ); goto bind; }
if(value & Joypad::HatRight) { type = Type::HatRight; encode.append(".Right"); goto bind; }
}
if(Joypad::isAnyAxis(scancode)) {
if(value < -12288) { type = Type::AxisLo; encode.append(".Lo"); goto bind; }
if(value > +24576) { type = Type::AxisHi; encode.append(".Hi"); goto bind; }
}
return false;
bind:
mapping = encode;
this->scancode = scancode;
this->type = type;
return true;
}
int16_t DigitalInput::poll() {
int16_t value = AbstractInput::poll();
switch(type) {
case Type::Button: return (bool)(value);
case Type::MouseButton: return (bool)(value & input.acquired());
case Type::HatUp: return (bool)(value & Joypad::HatUp);
case Type::HatDown: return (bool)(value & Joypad::HatDown);
case Type::HatLeft: return (bool)(value & Joypad::HatLeft);
case Type::HatRight: return (bool)(value & Joypad::HatRight);
case Type::AxisLo: return (bool)(value < -16384);
case Type::AxisHi: return (bool)(value > +16384);
}
return 0;
}
//
int16_t TurboInput::poll() {
int16_t result = DigitalInput::poll();
if(phase < 3) result = 0;
if(++phase >= 6) phase = 0;
return result;
}
TurboInput::TurboInput() : phase(0) {
}
//
void TertiaryInput::attach(const string &primaryName, const string &secondaryName) {
for(unsigned n = 0; n < size(); n++) {
operator[](n).attach(primaryName, secondaryName, name);
}
}
void TertiaryInput::bind() {
for(unsigned n = 0; n < size(); n++) {
operator[](n).bind();
}
}
int16_t TertiaryInput::poll(unsigned n) {
return operator[](n).poll();
}
//
void SecondaryInput::attach(const string &primaryName) {
for(unsigned n = 0; n < size(); n++) {
operator[](n).attach(primaryName, name);
}
}
void SecondaryInput::bind() {
for(unsigned n = 0; n < size(); n++) {
operator[](n).bind();
}
}
//
void PrimaryInput::attach() {
for(unsigned n = 0; n < size(); n++) {
operator[](n).attach(name);
}
}
void PrimaryInput::bind() {
for(unsigned n = 0; n < size(); n++) {
operator[](n).bind();
}
}
//
void InputManager::scan() {
activeScancode = !activeScancode;
input.poll(scancode[activeScancode]);
for(unsigned n = 0; n < Scancode::Limit; n++) {
if(scancode[!activeScancode][n] != scancode[activeScancode][n]) {
if(settingsWindow->focused()) inputSettings->inputEvent(n, scancode[activeScancode][n]);
if(mainWindow->focused()) userInterface.inputEvent(n, scancode[activeScancode][n]);
}
}
}
InputManager::InputManager() {
inputManager = this;
inputList.append(nes);
inputList.append(snes);
inputList.append(gameBoy);
inputList.append(userInterface);
for(unsigned n = 0; n < inputList.size(); n++) inputList[n].attach();
config.load(application->path("input.cfg"));
config.save(application->path("input.cfg"));
for(unsigned n = 0; n < inputList.size(); n++) inputList[n].bind();
activeScancode = 0;
}
InputManager::~InputManager() {
config.save(application->path("input.cfg"));
}