bsnes/target-ethos/settings/input.cpp

188 lines
6.2 KiB
C++

InputSettings* inputSettings = nullptr;
InputSettings::InputSettings() {
focusLabel.setText("When Focus is Lost:");
focusPause.setText("Pause Emulation");
focusAllow.setText("Allow Input");
inputList.setHeaderText({"Name", "Mapping"});
inputList.setHeaderVisible();
resetButton.setText("Reset");
eraseButton.setText("Erase");
append(focusLayout, {~0, 0}, 5);
focusLayout.append(focusLabel, {0, 0}, 5);
focusLayout.append(focusPause, {0, 0}, 5);
focusLayout.append(focusAllow, {0, 0});
append(selectionLayout, {~0, 0}, 5);
selectionLayout.append(systemList, {~0, 0}, 5);
selectionLayout.append(portList, {~0, 0}, 5);
selectionLayout.append(deviceList, {~0, 0});
append(inputList, {~0, ~0}, 5);
append(controlLayout, {~0, 0});
controlLayout.append(assign[0], {100, 0}, 5);
controlLayout.append(assign[1], {100, 0}, 5);
controlLayout.append(assign[2], {100, 0}, 5);
controlLayout.append(spacer, {~0, 0});
controlLayout.append(resetButton, {80, 0}, 5);
controlLayout.append(eraseButton, {80, 0});
for(auto& emulator : program->emulator) {
systemList.append(emulator->information.name);
}
focusPause.setChecked(config->input.focus.pause);
focusAllow.setChecked(config->input.focus.allow);
focusAllow.setEnabled(!config->input.focus.pause);
focusPause.onToggle = [&] { config->input.focus.pause = focusPause.checked(); focusAllow.setEnabled(!focusPause.checked()); };
focusAllow.onToggle = [&] { config->input.focus.allow = focusAllow.checked(); };
systemList.onChange = {&InputSettings::systemChanged, this};
portList.onChange = {&InputSettings::portChanged, this};
deviceList.onChange = {&InputSettings::deviceChanged, this};
inputList.onChange = {&InputSettings::synchronize, this};
inputList.onActivate = {&InputSettings::assignInput, this};
assign[0].onActivate = [&] { assignMouseInput(0); };
assign[1].onActivate = [&] { assignMouseInput(1); };
assign[2].onActivate = [&] { assignMouseInput(2); };
resetButton.onActivate = {&InputSettings::resetInput, this};
eraseButton.onActivate = {&InputSettings::eraseInput, this};
systemChanged();
}
void InputSettings::synchronize() {
if(inputList.selected() == false) {
assign[0].setVisible(false);
assign[1].setVisible(false);
assign[2].setVisible(false);
} else {
unsigned number = activeDevice().order[inputList.selection()];
auto& input = activeDevice().input[number];
auto selectedInput = inputManager->inputMap[input.guid];
if(dynamic_cast<DigitalInput*>(selectedInput)) {
assign[0].setText("Mouse Left");
assign[1].setText("Mouse Middle");
assign[2].setText("Mouse Right");
assign[0].setVisible(true);
assign[1].setVisible(true);
assign[2].setVisible(true);
}
if(dynamic_cast<RelativeInput*>(selectedInput)) {
assign[0].setText("Mouse X-axis");
assign[1].setText("Mouse Y-axis");
assign[0].setVisible(true);
assign[1].setVisible(true);
assign[2].setVisible(false);
}
}
eraseButton.setEnabled(inputList.selected());
}
Emulator::Interface& InputSettings::activeSystem() {
return *program->emulator[systemList.selection()];
}
Emulator::Interface::Port& InputSettings::activePort() {
return activeSystem().port[portList.selection()];
}
Emulator::Interface::Device& InputSettings::activeDevice() {
return activePort().device[deviceList.selection()];
}
void InputSettings::systemChanged() {
portList.reset();
for(auto& port : activeSystem().port) {
portList.append(port.name);
}
portChanged();
}
void InputSettings::portChanged() {
deviceList.reset();
for(auto& device : activePort().device) {
deviceList.append(device.name);
}
deviceChanged();
}
void InputSettings::deviceChanged() {
inputList.reset();
for(unsigned number : activeDevice().order) inputList.append({"", ""});
inputChanged();
synchronize();
}
void InputSettings::inputChanged() {
unsigned index = 0;
for(unsigned number : activeDevice().order) {
auto& input = activeDevice().input[number];
auto abstract = inputManager->inputMap(input.guid);
string mapping = inputManager->sanitize(abstract->mapping, " or ");
inputList.setText(index++, {input.name, mapping});
}
}
void InputSettings::resetInput() {
if(MessageWindow().setParent(*settings).setText("All inputs will be erased. Are you sure you want to do this?")
.question() == MessageWindow::Response::No) return;
auto& device = activeDevice();
unsigned length = device.input.size();
for(unsigned n = 0; n < length; n++) {
activeInput = inputManager->inputMap[device.input[n].guid];
inputEvent(hidNull, 0, 0, 0, 1);
}
}
void InputSettings::eraseInput() {
unsigned number = activeDevice().order[inputList.selection()];
auto& input = activeDevice().input[number];
activeInput = inputManager->inputMap[input.guid];
inputEvent(hidNull, 0, 0, 0, 1);
}
void InputSettings::assignInput() {
unsigned number = activeDevice().order[inputList.selection()];
auto& input = activeDevice().input[number];
activeInput = inputManager->inputMap[input.guid];
settings->setStatusText({"Set assignment for [", activeDevice().name, "::", input.name, "] ..."});
settings->layout.setEnabled(false);
setEnabled(false);
}
void InputSettings::assignMouseInput(unsigned n) {
unsigned number = activeDevice().order[inputList.selection()];
auto& input = activeDevice().input[number];
activeInput = inputManager->inputMap[input.guid];
if(dynamic_cast<DigitalInput*>(activeInput)) {
if(auto hidMouse = inputManager->findMouse()) {
return inputEvent(*hidMouse, HID::Mouse::GroupID::Button, n, 0, 1, true);
}
}
if(dynamic_cast<RelativeInput*>(activeInput)) {
if(auto hidMouse = inputManager->findMouse()) {
return inputEvent(*hidMouse, HID::Mouse::GroupID::Axis, n, 0, +32767, true);
}
}
}
void InputSettings::inputEvent(HID::Device& device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue, bool allowMouseInput) {
if(activeInput == nullptr) return;
if(allowMouseInput == false && device.isMouse()) return;
if(activeInput->bind(device, group, input, oldValue, newValue) == false) return;
activeInput = nullptr;
inputChanged();
settings->setStatusText("");
settings->layout.setEnabled(true);
setEnabled(true);
synchronize();
}