InputSettings::InputSettings(TabFrame* parent) : TabFrameItem(parent) { setIcon(Icon::Device::Joypad); setText("Input"); layout.setMargin(5); focusLabel.setText("When Focus is Lost:"); pauseEmulation.setText("Pause Emulation").setChecked(settings["Input/FocusLoss/Pause"].boolean()).onToggle([&] { settings["Input/FocusLoss/Pause"].setValue(pauseEmulation.checked()); allowInput.setEnabled(!pauseEmulation.checked()); }).doToggle(); allowInput.setText("Allow Input").setChecked(settings["Input/FocusLoss/AllowInput"].boolean()).onToggle([&] { settings["Input/FocusLoss/AllowInput"].setValue(allowInput.checked()); }); for(auto& emulator : inputManager->emulators) { emulatorList.append(ComboButtonItem().setText(emulator.name)); } emulatorList.onChange([&] { reloadPorts(); }); portList.onChange([&] { reloadDevices(); }); deviceList.onChange([&] { reloadMappings(); }); mappingList.onActivate([&] { assignMapping(); }); mappingList.onChange([&] { updateControls(); }); assignMouse1.setVisible(false).onActivate([&] { assignMouseInput(0); }); assignMouse2.setVisible(false).onActivate([&] { assignMouseInput(1); }); assignMouse3.setVisible(false).onActivate([&] { assignMouseInput(2); }); resetButton.setText("Reset").onActivate([&] { if(MessageDialog("Are you sure you want to erase all mappings for this device?").setParent(*settingsManager).question() == "Yes") { for(auto& mapping : activeDevice().mappings) mapping->unbind(); refreshMappings(); } }); eraseButton.setText("Erase").onActivate([&] { if(auto mapping = mappingList.selected()) { activeDevice().mappings[mapping->offset()]->unbind(); refreshMappings(); } }); reloadPorts(); } auto InputSettings::updateControls() -> void { eraseButton.setEnabled((bool)mappingList.selected()); assignMouse1.setVisible(false); assignMouse2.setVisible(false); assignMouse3.setVisible(false); if(auto mapping = mappingList.selected()) { auto input = activeDevice().mappings[mapping->offset()]; if(input->isDigital()) { assignMouse1.setVisible().setText("Mouse Left"); assignMouse2.setVisible().setText("Mouse Middle"); assignMouse3.setVisible().setText("Mouse Right"); } else if(input->isAnalog()) { assignMouse1.setVisible().setText("Mouse X-axis"); assignMouse2.setVisible().setText("Mouse Y-axis"); } } } auto InputSettings::activeEmulator() -> InputEmulator& { return inputManager->emulators[emulatorList.selected().offset()]; } auto InputSettings::activePort() -> InputPort& { return activeEmulator().ports[portList.selected().offset()]; } auto InputSettings::activeDevice() -> InputDevice& { auto index = deviceList.selected().property("index").natural(); return activePort().devices[index]; } auto InputSettings::reloadPorts() -> void { portList.reset(); for(auto& port : activeEmulator().ports) { portList.append(ComboButtonItem().setText(port.name)); } reloadDevices(); } auto InputSettings::reloadDevices() -> void { deviceList.reset(); for(auto n : range(activePort().devices)) { auto& device = activePort().devices[n]; if(!device.mappings) continue; //do not display devices that have no configurable inputs deviceList.append(ComboButtonItem().setText(device.name).setProperty("index", n)); } reloadMappings(); } auto InputSettings::reloadMappings() -> void { eraseButton.setEnabled(false); mappingList.reset(); mappingList.append(ListViewHeader().setVisible() .append(ListViewColumn().setText("Name")) .append(ListViewColumn().setText("Mapping").setExpandable()) .append(ListViewColumn().setText("Device").setAlignment(1.0).setForegroundColor({0, 128, 0})) ); for(auto& mapping : activeDevice().mappings) { mappingList.append(ListViewItem() .append(ListViewCell().setText(mapping->name)) .append(ListViewCell()) .append(ListViewCell()) ); } refreshMappings(); } auto InputSettings::refreshMappings() -> void { uint position = 0; for(auto& mapping : activeDevice().mappings) { mappingList.item(position)->cell(1)->setText(mapping->assignmentName()); mappingList.item(position)->cell(2)->setText(mapping->deviceName()); position++; } mappingList.resizeColumns(); } auto InputSettings::assignMapping() -> void { inputManager->poll(); //clear any pending events first if(auto mapping = mappingList.selected()) { activeMapping = activeDevice().mappings[mapping->offset()]; settingsManager->layout.setEnabled(false); settingsManager->statusBar.setText({"Press a key or button to map [", activeMapping->name, "] ..."}); } } auto InputSettings::assignMouseInput(uint id) -> void { if(auto mouse = inputManager->findMouse()) { if(auto mapping = mappingList.selected()) { activeMapping = activeDevice().mappings[mapping->offset()]; if(activeMapping->isDigital()) { return inputEvent(mouse, HID::Mouse::GroupID::Button, id, 0, 1, true); } else if(activeMapping->isAnalog()) { return inputEvent(mouse, HID::Mouse::GroupID::Axis, id, 0, +32767, true); } } } } auto InputSettings::inputEvent(shared_pointer device, uint group, uint input, int16 oldValue, int16 newValue, bool allowMouseInput) -> void { if(!activeMapping) return; if(device->isMouse() && !allowMouseInput) return; if(activeMapping->bind(device, group, input, oldValue, newValue)) { activeMapping = nullptr; settingsManager->statusBar.setText("Mapping assigned."); refreshMappings(); timer.onActivate([&] { timer.setEnabled(false); settingsManager->statusBar.setText(); settingsManager->layout.setEnabled(); }).setInterval(200).setEnabled(); } }