mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-13 12:39:56 +00:00
KEYMAPPER: Multiple inputs can map to the same action
This commit is contained in:
parent
d5e2b5d8f2
commit
ade0efa762
@ -25,6 +25,7 @@
|
||||
#ifdef ENABLE_KEYMAPPER
|
||||
|
||||
#include "common/system.h"
|
||||
#include "common/tokenizer.h"
|
||||
|
||||
#include "backends/keymapper/action.h"
|
||||
#include "backends/keymapper/hardware-input.h"
|
||||
@ -54,27 +55,43 @@ void Keymap::addAction(Action *action) {
|
||||
}
|
||||
|
||||
void Keymap::registerMapping(Action *action, const HardwareInput *hwInput) {
|
||||
unregisterMapping(action);
|
||||
ActionArray &actionArray = _hwActionMap.getVal(hwInput);
|
||||
|
||||
_hwActionMap[hwInput] = action;
|
||||
// Don't allow an input to map to the same action multiple times
|
||||
ActionArray::const_iterator found = find(actionArray.begin(), actionArray.end(), action);
|
||||
if (found == actionArray.end()) {
|
||||
actionArray.push_back(action);
|
||||
}
|
||||
}
|
||||
|
||||
void Keymap::unregisterMapping(Action *action) {
|
||||
for (HardwareActionMap::iterator it = _hwActionMap.begin(); it != _hwActionMap.end(); it++) {
|
||||
if (it->_value == action) {
|
||||
_hwActionMap.erase(it);
|
||||
// Remove the action from all the input mappings
|
||||
for (HardwareActionMap::iterator itInput = _hwActionMap.begin(); itInput != _hwActionMap.end(); itInput++) {
|
||||
for (ActionArray::iterator itAction = itInput->_value.begin(); itAction != itInput->_value.end(); itAction++) {
|
||||
if (*itAction == action) {
|
||||
itInput->_value.erase(itAction);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (itInput->_value.empty()) {
|
||||
_hwActionMap.erase(itInput);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const HardwareInput *Keymap::getActionMapping(Action *action) const {
|
||||
for (HardwareActionMap::const_iterator it = _hwActionMap.begin(); it != _hwActionMap.end(); it++) {
|
||||
if (it->_value == action) {
|
||||
return it->_key;
|
||||
Array<const HardwareInput *> Keymap::getActionMapping(Action *action) const {
|
||||
Array<const HardwareInput *> inputs;
|
||||
|
||||
for (HardwareActionMap::iterator itInput = _hwActionMap.begin(); itInput != _hwActionMap.end(); itInput++) {
|
||||
for (ActionArray::iterator itAction = itInput->_value.begin(); itAction != itInput->_value.end(); itAction++) {
|
||||
if (*itAction == action) {
|
||||
inputs.push_back(itInput->_key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return inputs;
|
||||
}
|
||||
|
||||
const Action *Keymap::findAction(const char *id) const {
|
||||
@ -86,7 +103,7 @@ const Action *Keymap::findAction(const char *id) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Action *Keymap::getMappedAction(const HardwareInput *hardwareInput) const {
|
||||
const Keymap::ActionArray &Keymap::getMappedActions(const HardwareInput *hardwareInput) const {
|
||||
return _hwActionMap[hardwareInput];
|
||||
}
|
||||
|
||||
@ -95,34 +112,35 @@ void Keymap::setConfigDomain(ConfigManager::Domain *dom) {
|
||||
}
|
||||
|
||||
void Keymap::loadMappings(const HardwareInputSet *hwKeys) {
|
||||
if (!_configDomain)
|
||||
return;
|
||||
assert(_configDomain);
|
||||
|
||||
if (_actions.empty())
|
||||
if (_actions.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String prefix = KEYMAP_KEY_PREFIX + _name + "_";
|
||||
|
||||
_hwActionMap.clear();
|
||||
for (ActionArray::const_iterator it = _actions.begin(); it != _actions.end(); ++it) {
|
||||
Action* ua = *it;
|
||||
String actionId(ua->id);
|
||||
String confKey = prefix + actionId;
|
||||
|
||||
String hwInputId = _configDomain->getVal(confKey);
|
||||
// The configuration value is a list of space separated hardware input ids
|
||||
StringTokenizer hwInputIds = _configDomain->getVal(confKey);
|
||||
|
||||
// there's no mapping
|
||||
if (hwInputId.empty())
|
||||
continue;
|
||||
String hwInputId;
|
||||
while ((hwInputId = hwInputIds.nextToken()) != "") {
|
||||
const HardwareInput *hwInput = hwKeys->findHardwareInput(hwInputId.c_str());
|
||||
|
||||
const HardwareInput *hwInput = hwKeys->findHardwareInput(hwInputId.c_str());
|
||||
if (!hwInput) {
|
||||
warning("HardwareInput with ID '%s' not known", hwInputId.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!hwInput) {
|
||||
warning("HardwareInput with ID '%s' not known", hwInputId.c_str());
|
||||
continue;
|
||||
// map the key
|
||||
registerMapping(ua, hwInput);
|
||||
}
|
||||
|
||||
// map the key
|
||||
_hwActionMap[hwInput] = ua;
|
||||
}
|
||||
}
|
||||
|
||||
@ -132,11 +150,21 @@ void Keymap::saveMappings() {
|
||||
|
||||
String prefix = KEYMAP_KEY_PREFIX + _name + "_";
|
||||
|
||||
for (HardwareActionMap::const_iterator it = _hwActionMap.begin(); it != _hwActionMap.end(); it++) {
|
||||
const Action *action = it->_value;
|
||||
const HardwareInput *input = it->_key;
|
||||
for (ActionArray::const_iterator it = _actions.begin(); it != _actions.end(); it++) {
|
||||
Action *action = *it;
|
||||
Array<const HardwareInput *> mappedInputs = getActionMapping(action);
|
||||
|
||||
_configDomain->setVal(prefix + action->id, input->id);
|
||||
// The configuration value is a list of space separated hardware input ids
|
||||
String confValue;
|
||||
for (uint j = 0; j < mappedInputs.size(); j++) {
|
||||
if (!confValue.empty()) {
|
||||
confValue += " ";
|
||||
}
|
||||
|
||||
confValue += mappedInputs[j]->id;
|
||||
}
|
||||
|
||||
_configDomain->setVal(prefix + action->id, confValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,14 +70,14 @@ public:
|
||||
/**
|
||||
* Find the hardware input an action is mapped to, if any
|
||||
*/
|
||||
const HardwareInput *getActionMapping(Action *action) const;
|
||||
Array<const HardwareInput *> getActionMapping(Action *action) const;
|
||||
|
||||
/**
|
||||
* Find the Action that a hardware input is mapped to
|
||||
* Find the Actions that a hardware input is mapped to
|
||||
* @param hardwareInput the input that is mapped to the required Action
|
||||
* @return a pointer to the Action or 0 if no
|
||||
* @return an array containing pointers to the actions
|
||||
*/
|
||||
Action *getMappedAction(const HardwareInput *hardwareInput) const;
|
||||
const ActionArray &getMappedActions(const HardwareInput *hardwareInput) const;
|
||||
|
||||
/**
|
||||
* Get the list of all the Actions contained in this Keymap
|
||||
@ -120,7 +120,7 @@ private:
|
||||
|
||||
const Action *findAction(const char *id) const;
|
||||
|
||||
typedef HashMap<const HardwareInput *, Action *> HardwareActionMap;
|
||||
typedef HashMap<const HardwareInput *, ActionArray> HardwareActionMap;
|
||||
|
||||
KeymapType _type;
|
||||
String _name;
|
||||
|
@ -135,6 +135,8 @@ List<Event> Keymapper::mapEvent(const Event &ev, EventSource *source) {
|
||||
return DefaultEventMapper::mapEvent(ev, source);
|
||||
}
|
||||
|
||||
IncomingEventType incomingEventType = convertToIncomingEventType(ev);
|
||||
|
||||
List<Event> mappedEvents;
|
||||
for (int i = _keymaps.size() - 1; i >= 0; --i) {
|
||||
if (!_keymaps[i]->isEnabled()) {
|
||||
@ -148,10 +150,13 @@ List<Event> Keymapper::mapEvent(const Event &ev, EventSource *source) {
|
||||
|
||||
debug(5, "Keymapper::mapKey keymap: %s", _keymaps[i]->getName().c_str());
|
||||
|
||||
Action *action = _keymaps[i]->getMappedAction(hwInput);
|
||||
if (action) {
|
||||
IncomingEventType incomingEventType = convertToIncomingEventType(ev);
|
||||
mappedEvents.push_back(executeAction(action, incomingEventType));
|
||||
const Keymap::ActionArray &actions = _keymaps[i]->getMappedActions(hwInput);
|
||||
for (Keymap::ActionArray::const_iterator it = actions.begin(); it != actions.end(); it++) {
|
||||
mappedEvents.push_back(executeAction(*it, incomingEventType));
|
||||
}
|
||||
if (!actions.empty()) {
|
||||
// If we found actions matching this input in a keymap, no need to look at the other keymaps.
|
||||
// An input resulting in actions from system and game keymaps would lead to unexpected user experience.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -241,9 +241,19 @@ void RemapDialog::refreshKeymap() {
|
||||
|
||||
Keymap *keymap = row.action->getParent();
|
||||
|
||||
const HardwareInput *mappedInput = keymap->getActionMapping(row.action);
|
||||
if (mappedInput)
|
||||
row.keyButton->setLabel(mappedInput->description);
|
||||
Array<const HardwareInput *> mappedInputs = keymap->getActionMapping(row.action);
|
||||
|
||||
String keysLabel;
|
||||
for (uint j = 0; j < mappedInputs.size(); j++) {
|
||||
if (!keysLabel.empty()) {
|
||||
keysLabel += ", ";
|
||||
}
|
||||
|
||||
keysLabel += mappedInputs[j]->description;
|
||||
}
|
||||
|
||||
if (!keysLabel.empty())
|
||||
row.keyButton->setLabel(keysLabel);
|
||||
else
|
||||
row.keyButton->setLabel("-");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user