bsnes/target-tomoko/input/input.cpp

140 lines
3.8 KiB
C++

#include "../tomoko.hpp"
#include "hotkeys.cpp"
InputManager* inputManager = nullptr;
auto InputMapping::bind() -> void {
auto token = assignment.split("/");
if(token.size() < 3) return;
uint64_t id = token[0].hex();
unsigned group = token[1].decimal();
unsigned input = token[2].decimal();
for(auto& device : inputManager->devices) {
if(id != device->id) continue;
this->device = device;
this->group = group;
this->input = input;
break;
}
}
auto InputMapping::bind(HID::Device& device, unsigned group, unsigned input, int16 oldValue, int16 newValue) -> bool {
if(device.group[group].input[input].name == "Escape") return unbind(), true;
this->assignment = {hex(device.id), "/", group, "/", input, "/", device.group[group].input[input].name};
this->device = &device;
this->group = group;
this->input = input;
return true;
}
auto InputMapping::poll() -> int16 {
if(device) return device->group[group].input[input].value;
return 0;
}
auto InputMapping::unbind() -> void {
this->assignment = "None";
this->device = nullptr;
this->group = 0;
this->input = 0;
}
//
InputManager::InputManager() {
inputManager = this;
input.onChange = {&InputManager::onChange, this};
for(auto& emulator : program->emulators) {
Configuration::Node nodeEmulator;
emulators.append(InputEmulator());
auto& inputEmulator = emulators.last();
inputEmulator.name = emulator->information.name;
for(auto& port : emulator->port) {
Configuration::Node nodePort;
inputEmulator.ports.append(InputPort());
auto& inputPort = inputEmulator.ports.last();
inputPort.name = port.name;
for(auto& device : port.device) {
Configuration::Node nodeDevice;
inputPort.devices.append(InputDevice());
auto& inputDevice = inputPort.devices.last();
inputDevice.name = device.name;
for(auto number : device.order) {
auto& input = device.input[number];
inputDevice.mappings.append(new InputMapping());
auto& inputMapping = inputDevice.mappings.last();
inputMapping->name = input.name;
inputMapping->link = &input;
input.guid = (uintptr_t)inputMapping;
nodeDevice.append(inputMapping->assignment, inputMapping->name);
}
nodePort.append(nodeDevice, string{inputDevice.name}.replace(" ", ""));
}
nodeEmulator.append(nodePort, string{inputPort.name}.replace(" ", ""));
}
config.append(nodeEmulator, string{inputEmulator.name}.replace(" ", ""));
}
appendHotkeys();
config.load({configpath(), "tomoko/input.bml"});
config.save({configpath(), "tomoko/input.bml"});
poll(); //will call bind();
}
auto InputManager::bind() -> void {
for(auto& emulator : emulators) {
for(auto& port : emulator.ports) {
for(auto& device : port.devices) {
for(auto& mapping : device.mappings) {
mapping->bind();
}
}
}
}
for(auto& hotkey : hotkeys) {
hotkey->bind();
}
}
auto InputManager::poll() -> void {
auto devices = input.poll();
bool changed = devices.size() != this->devices.size();
if(changed == false) {
for(auto n : range(devices)) {
changed = devices[n] != this->devices[n];
if(changed) break;
}
}
if(changed == true) {
this->devices = devices;
bind();
}
if(presentation && presentation->focused()) pollHotkeys();
}
auto InputManager::onChange(HID::Device& device, unsigned group, unsigned input, int16 oldValue, int16 newValue) -> void {
if(settingsManager->focused()) {
settingsManager->input.inputEvent(device, group, input, oldValue, newValue);
settingsManager->hotkeys.inputEvent(device, group, input, oldValue, newValue);
}
}
auto InputManager::quit() -> void {
config.save({configpath(), "tomoko/input.bml"});
emulators.reset();
hotkeys.reset();
}