reduce operation delay by optimizing key-map

This commit is contained in:
Tian Zhou 2019-11-19 02:46:18 -05:00
commit 14fc57ced6
3 changed files with 303 additions and 179 deletions

View file

@ -68,7 +68,7 @@ void InputConvertGame::keyEvent(const QKeyEvent *from, const QSize& frameSize, c
return; return;
} }
KeyMap::KeyMapNode& node = m_keyMap.getKeyMapNode(from->key()); KeyMap::KeyMapNode& node = m_keyMap.getKeyMapNodeKey(from->key());
// 处理特殊按键:可以在按键映射和普通映射间切换的按键 // 处理特殊按键:可以在按键映射和普通映射间切换的按键
if (m_needSwitchGameAgain if (m_needSwitchGameAgain
&& KeyMap::KMT_CLICK == node.type && KeyMap::KMT_CLICK == node.type
@ -225,13 +225,13 @@ int InputConvertGame::updateSteerWheelKeysPress(KeyMap::KeyMapNode &node, const
} else if (QEvent::KeyRelease == from->type()) { } else if (QEvent::KeyRelease == from->type()) {
keyPress = false; keyPress = false;
} }
if (from->key() == node.steerWheel.upKey) { if (from->key() == node.steerWheel.up.key) {
node.steerWheel.upKeyPressed = keyPress; node.steerWheel.upKeyPressed = keyPress;
} else if (from->key() == node.steerWheel.rightKey) { } else if (from->key() == node.steerWheel.right.key) {
node.steerWheel.rightKeyPressed = keyPress; node.steerWheel.rightKeyPressed = keyPress;
} else if (from->key() == node.steerWheel.downKey) { } else if (from->key() == node.steerWheel.down.key) {
node.steerWheel.downKeyPressed = keyPress; node.steerWheel.downKeyPressed = keyPress;
} else if (from->key() == node.steerWheel.leftKey) { } else if (from->key() == node.steerWheel.left.key) {
node.steerWheel.leftKeyPressed = keyPress; node.steerWheel.leftKeyPressed = keyPress;
} }
@ -243,33 +243,33 @@ int InputConvertGame::updateSteerWheelKeysPress(KeyMap::KeyMapNode &node, const
if (node.steerWheel.upKeyPressed) { if (node.steerWheel.upKeyPressed) {
count++; count++;
if (Qt::Key_unknown == keyPress1) { if (Qt::Key_unknown == keyPress1) {
keyPress1 = node.steerWheel.upKey; keyPress1 = node.steerWheel.up.key;
} else if (Qt::Key_unknown == keyPress2) { } else if (Qt::Key_unknown == keyPress2) {
keyPress2 = node.steerWheel.upKey; keyPress2 = node.steerWheel.up.key;
} }
} }
if (node.steerWheel.rightKeyPressed) { if (node.steerWheel.rightKeyPressed) {
count++; count++;
if (Qt::Key_unknown == keyPress1) { if (Qt::Key_unknown == keyPress1) {
keyPress1 = node.steerWheel.rightKey; keyPress1 = node.steerWheel.right.key;
} else if (Qt::Key_unknown == keyPress2) { } else if (Qt::Key_unknown == keyPress2) {
keyPress2 = node.steerWheel.rightKey; keyPress2 = node.steerWheel.right.key;
} }
} }
if (node.steerWheel.downKeyPressed) { if (node.steerWheel.downKeyPressed) {
count++; count++;
if (Qt::Key_unknown == keyPress1) { if (Qt::Key_unknown == keyPress1) {
keyPress1 = node.steerWheel.downKey; keyPress1 = node.steerWheel.down.key;
} else if (Qt::Key_unknown == keyPress2) { } else if (Qt::Key_unknown == keyPress2) {
keyPress2 = node.steerWheel.downKey; keyPress2 = node.steerWheel.down.key;
} }
} }
if (node.steerWheel.leftKeyPressed) { if (node.steerWheel.leftKeyPressed) {
count++; count++;
if (Qt::Key_unknown == keyPress1) { if (Qt::Key_unknown == keyPress1) {
keyPress1 = node.steerWheel.leftKey; keyPress1 = node.steerWheel.left.key;
} else if (Qt::Key_unknown == keyPress2) { } else if (Qt::Key_unknown == keyPress2) {
keyPress2 = node.steerWheel.leftKey; keyPress2 = node.steerWheel.left.key;
} }
} }
return count; return count;
@ -283,24 +283,24 @@ void InputConvertGame::steerWheelMove(KeyMap::KeyMapNode &node, int keysNum, int
QPointF movePos = node.steerWheel.centerPos; QPointF movePos = node.steerWheel.centerPos;
switch (keysNum) { switch (keysNum) {
case 2: case 2:
if (keyPress2 == node.steerWheel.upKey) { if (keyPress2 == node.steerWheel.up.key) {
movePos.setY(movePos.y() - node.steerWheel.upOffset); movePos.setY(movePos.y() - node.steerWheel.up.offset);
} else if (keyPress2 == node.steerWheel.rightKey) { } else if (keyPress2 == node.steerWheel.right.key) {
movePos.setX(movePos.x() + node.steerWheel.rightOffset); movePos.setX(movePos.x() + node.steerWheel.right.offset);
} else if (keyPress2 == node.steerWheel.downKey) { } else if (keyPress2 == node.steerWheel.down.key) {
movePos.setY(movePos.y() + node.steerWheel.downOffset); movePos.setY(movePos.y() + node.steerWheel.down.offset);
} else if (keyPress2 == node.steerWheel.leftKey) { } else if (keyPress2 == node.steerWheel.left.key) {
movePos.setX(movePos.x() - node.steerWheel.leftOffset); movePos.setX(movePos.x() - node.steerWheel.left.offset);
} }
case 1: case 1:
if (keyPress1 == node.steerWheel.upKey) { if (keyPress1 == node.steerWheel.up.key) {
movePos.setY(movePos.y() - node.steerWheel.upOffset); movePos.setY(movePos.y() - node.steerWheel.up.offset);
} else if (keyPress1 == node.steerWheel.rightKey) { } else if (keyPress1 == node.steerWheel.right.key) {
movePos.setX(movePos.x() + node.steerWheel.rightOffset); movePos.setX(movePos.x() + node.steerWheel.right.offset);
} else if (keyPress1 == node.steerWheel.downKey) { } else if (keyPress1 == node.steerWheel.down.key) {
movePos.setY(movePos.y() + node.steerWheel.downOffset); movePos.setY(movePos.y() + node.steerWheel.down.offset);
} else if (keyPress1 == node.steerWheel.leftKey) { } else if (keyPress1 == node.steerWheel.left.key) {
movePos.setX(movePos.x() - node.steerWheel.leftOffset); movePos.setX(movePos.x() - node.steerWheel.left.offset);
} }
break; break;
} }
@ -333,7 +333,7 @@ void InputConvertGame::processKeyClick(QPointF clickPos, bool clickTwice, bool s
bool InputConvertGame::processMouseClick(const QMouseEvent *from) bool InputConvertGame::processMouseClick(const QMouseEvent *from)
{ {
KeyMap::KeyMapNode& node = m_keyMap.getKeyMapNode(from->button()); KeyMap::KeyMapNode& node = m_keyMap.getKeyMapNodeMouse(from->button());
if (KeyMap::KMT_INVALID == node.type) { if (KeyMap::KMT_INVALID == node.type) {
return false; return false;
} }
@ -373,9 +373,9 @@ bool InputConvertGame::processMouseMove(const QMouseEvent *from)
m_mouseMoveLastConverPos.setY(m_mouseMoveLastConverPos.y() + distance.y() / m_showSize.height()); m_mouseMoveLastConverPos.setY(m_mouseMoveLastConverPos.y() + distance.y() / m_showSize.height());
if (m_mouseMoveLastConverPos.x() < 0.1 if (m_mouseMoveLastConverPos.x() < 0.1
|| m_mouseMoveLastConverPos.x() > 0.8 || m_mouseMoveLastConverPos.x() > 0.9
|| m_mouseMoveLastConverPos.y() < 0.1 || m_mouseMoveLastConverPos.y() < 0.1
|| m_mouseMoveLastConverPos.y() > 0.8) { || m_mouseMoveLastConverPos.y() > 0.9) {
mouseMoveStopTouch(); mouseMoveStopTouch();
mouseMoveStartTouch(from); mouseMoveStartTouch(from);
} }
@ -389,8 +389,8 @@ bool InputConvertGame::processMouseMove(const QMouseEvent *from)
void InputConvertGame::moveCursorToStart(const QMouseEvent *from) void InputConvertGame::moveCursorToStart(const QMouseEvent *from)
{ {
QPointF mouseMoveStartPos = m_keyMap.getMouseMoveMap().startPos; QPointF mouseMoveStartPos = m_keyMap.getMouseMoveMap().startPos;
QPoint localPos = QPoint(m_showSize.width()*mouseMoveStartPos.x(), QPoint localPos = QPoint(static_cast<int>(m_showSize.width()*mouseMoveStartPos.x()),
m_showSize.height()*mouseMoveStartPos.y()); static_cast<int>(m_showSize.height()*mouseMoveStartPos.y()));
QPoint posOffset = from->localPos().toPoint() - localPos; QPoint posOffset = from->localPos().toPoint() - localPos;
QPoint globalPos = from->globalPos(); QPoint globalPos = from->globalPos();
@ -404,7 +404,7 @@ void InputConvertGame::moveCursorTo(const QMouseEvent *from, const QPoint &pos)
QPoint globalPos = from->globalPos(); QPoint globalPos = from->globalPos();
globalPos -= posOffset; globalPos -= posOffset;
qWarning() <<"move to: "<<globalPos; //qWarning() <<"move to: "<<globalPos;
QCursor::setPos(globalPos); QCursor::setPos(globalPos);
} }

View file

@ -41,10 +41,6 @@ void KeyMap::loadKeyMap(const QString &json)
QJsonDocument jsonDoc; QJsonDocument jsonDoc;
QJsonObject rootObj; QJsonObject rootObj;
QMetaEnum metaEnumKey = QMetaEnum::fromType<Qt::Key>();
QMetaEnum metaEnumMouseButtons = QMetaEnum::fromType<Qt::MouseButtons>();
QMetaEnum metaEnumKeyMapType = QMetaEnum::fromType<KeyMap::KeyMapType>();
jsonDoc = QJsonDocument::fromJson(json.toUtf8(), &jsonError); jsonDoc = QJsonDocument::fromJson(json.toUtf8(), &jsonError);
if(jsonError.error != QJsonParseError::NoError) if(jsonError.error != QJsonParseError::NoError)
@ -56,20 +52,13 @@ void KeyMap::loadKeyMap(const QString &json)
// switchKey // switchKey
rootObj = jsonDoc.object(); rootObj = jsonDoc.object();
if (rootObj.contains("switchKey") && rootObj.value("switchKey").isString()) { if (rootObj.contains("switchKey") && rootObj.value("switchKey").isString()) {
QString name = rootObj.value("switchKey").toString(); QPair<ActionType, int> p = getItemKey(rootObj, "switchKey");
int key = metaEnumKey.keyToValue(name.toStdString().c_str()); if(p.first == AT_INVALID){
int btn = metaEnumMouseButtons.keyToValue(name.toStdString().c_str());
if(key == -1 && btn == -1){
errorString = QString("json error: switchKey invalid"); errorString = QString("json error: switchKey invalid");
goto parseError; goto parseError;
} }
if(key != -1){ m_switchType = p.first;
m_switchType = AT_KEY; m_switchKey = p.second;
m_switchKey = key;
}else{
m_switchType = AT_MOUSE;
m_switchKey = btn;
}
} else { } else {
errorString = QString("json error: no find switchKey"); errorString = QString("json error: no find switchKey");
goto parseError; goto parseError;
@ -114,106 +103,73 @@ void KeyMap::loadKeyMap(const QString &json)
goto parseError; goto parseError;
} }
KeyMap::KeyMapType type = (KeyMap::KeyMapType)metaEnumKeyMapType.keyToValue(node.value("type").toString().toStdString().c_str()); KeyMap::KeyMapType type = getItemType(node, "type");
switch (type) { switch (type) {
case KeyMap::KMT_CLICK: case KeyMap::KMT_CLICK:
{ {
// safe check // safe check
if (!node.contains("key") || !node.value("key").isString() if (!checkForClick(node)) {
|| !node.contains("pos") || !node.value("pos").isObject()
|| !node.value("pos").toObject().contains("x") || !node.value("pos").toObject().value("x").isDouble()
|| !node.value("pos").toObject().contains("y") || !node.value("pos").toObject().value("y").isDouble()
|| !node.contains("switchMap") || !node.value("switchMap").isBool()
) {
qWarning() << "json error: keyMapNodes node format error"; qWarning() << "json error: keyMapNodes node format error";
break; break;
} }
QPair<ActionType, int> key = getItemKey(node, "key");
Qt::Key key = (Qt::Key)metaEnumKey.keyToValue(node.value("key").toString().toStdString().c_str()); if(key.first == AT_INVALID){
Qt::MouseButtons btn = (Qt::MouseButtons)metaEnumMouseButtons.keyToValue(node.value("key").toString().toStdString().c_str());
if (-1 == key && -1 == btn) {
qWarning() << "json error: keyMapNodes node invalid key: " << node.value("key").toString(); qWarning() << "json error: keyMapNodes node invalid key: " << node.value("key").toString();
break; break;
} }
KeyMapNode keyMapNode; KeyMapNode keyMapNode;
keyMapNode.type = type; keyMapNode.type = type;
if (key != -1) { keyMapNode.click.keyNode.type = key.first;
keyMapNode.click.keyNode.key = key; keyMapNode.click.keyNode.key = key.second;
} else { keyMapNode.click.keyNode.pos = getItemPos(node, "pos");
keyMapNode.click.keyNode.key = btn; keyMapNode.click.switchMap = getItemSwitchMap(node, "switchMap");
}
keyMapNode.click.keyNode.pos = QPointF(node.value("pos").toObject().value("x").toDouble(),
node.value("pos").toObject().value("y").toDouble());
keyMapNode.click.switchMap = node.value("switchMap").toBool();
m_keyMapNodes.push_back(keyMapNode); m_keyMapNodes.push_back(keyMapNode);
} }
break; break;
case KeyMap::KMT_CLICK_TWICE: case KeyMap::KMT_CLICK_TWICE:
{ {
// safe check // safe check
if (!node.contains("key") || !node.value("key").isString() if (!checkForClickDouble(node)) {
|| !node.contains("pos") || !node.value("pos").isObject()
|| !node.value("pos").toObject().contains("x") || !node.value("pos").toObject().value("x").isDouble()
|| !node.value("pos").toObject().contains("y") || !node.value("pos").toObject().value("y").isDouble()
) {
qWarning() << "json error: keyMapNodes node format error"; qWarning() << "json error: keyMapNodes node format error";
break; break;
} }
Qt::Key key = (Qt::Key)metaEnumKey.keyToValue(node.value("key").toString().toStdString().c_str()); QPair<ActionType, int> key = getItemKey(node, "key");
Qt::MouseButtons btn = (Qt::MouseButtons)metaEnumMouseButtons.keyToValue(node.value("key").toString().toStdString().c_str()); if(key.first == AT_INVALID){
if (-1 == key && -1 == btn) {
qWarning() << "json error: keyMapNodes node invalid key: " << node.value("key").toString(); qWarning() << "json error: keyMapNodes node invalid key: " << node.value("key").toString();
break; break;
} }
KeyMapNode keyMapNode; KeyMapNode keyMapNode;
keyMapNode.type = type; keyMapNode.type = type;
if (key != -1) { keyMapNode.click.keyNode.type = key.first;
keyMapNode.clickTwice.keyNode.key = key; keyMapNode.click.keyNode.key = key.second;
} else { keyMapNode.click.keyNode.pos = getItemPos(node, "pos");
keyMapNode.clickTwice.keyNode.key = btn; keyMapNode.click.switchMap = getItemSwitchMap(node, "switchMap");
}
keyMapNode.clickTwice.keyNode.pos = QPointF(node.value("pos").toObject().value("x").toDouble(),
node.value("pos").toObject().value("y").toDouble());
m_keyMapNodes.push_back(keyMapNode); m_keyMapNodes.push_back(keyMapNode);
} }
break; break;
case KeyMap::KMT_STEER_WHEEL: case KeyMap::KMT_STEER_WHEEL:
{ {
// safe check // safe check
if (!node.contains("leftKey") || !node.value("leftKey").isString() if(!checkForSteerWhell(node)){
|| !node.contains("rightKey") || !node.value("rightKey").isString()
|| !node.contains("upKey") || !node.value("upKey").isString()
|| !node.contains("downKey") || !node.value("downKey").isString()
|| !node.contains("leftOffset") || !node.value("leftOffset").isDouble()
|| !node.contains("rightOffset") || !node.value("rightOffset").isDouble()
|| !node.contains("upOffset") || !node.value("upOffset").isDouble()
|| !node.contains("downOffset") || !node.value("downOffset").isDouble()
|| !node.contains("centerPos") || !node.value("centerPos").isObject()
|| !node.value("centerPos").toObject().contains("x") || !node.value("centerPos").toObject().value("x").isDouble()
|| !node.value("centerPos").toObject().contains("y") || !node.value("centerPos").toObject().value("y").isDouble()
) {
qWarning() << "json error: keyMapNodes node format error"; qWarning() << "json error: keyMapNodes node format error";
break; break;
} }
QPair<ActionType, int> leftKey = getItemKey(node, "leftKey");
Qt::Key leftKey = (Qt::Key)metaEnumKey.keyToValue(node.value("leftKey").toString().toStdString().c_str()); QPair<ActionType, int> rightKey = getItemKey(node, "rightKey");
Qt::MouseButtons leftBtn = (Qt::MouseButtons)metaEnumMouseButtons.keyToValue(node.value("leftKey").toString().toStdString().c_str()); QPair<ActionType, int> upKey = getItemKey(node, "upKey");
Qt::Key rightKey = (Qt::Key)metaEnumKey.keyToValue(node.value("rightKey").toString().toStdString().c_str()); QPair<ActionType, int> downKey = getItemKey(node, "downKey");
Qt::MouseButtons rightBtn = (Qt::MouseButtons)metaEnumMouseButtons.keyToValue(node.value("rightKey").toString().toStdString().c_str()); if(leftKey.first == AT_INVALID || rightKey.first == AT_INVALID
Qt::Key upKey = (Qt::Key)metaEnumKey.keyToValue(node.value("upKey").toString().toStdString().c_str()); || upKey.first == AT_INVALID || downKey.first == AT_INVALID)
Qt::MouseButtons upBtn = (Qt::MouseButtons)metaEnumMouseButtons.keyToValue(node.value("upKey").toString().toStdString().c_str()); {
Qt::Key downKey = (Qt::Key)metaEnumKey.keyToValue(node.value("downKey").toString().toStdString().c_str()); if(leftKey.first == AT_INVALID)
Qt::MouseButtons downBtn = (Qt::MouseButtons)metaEnumMouseButtons.keyToValue(node.value("downKey").toString().toStdString().c_str()); qWarning() << "json error: keyMapNodes node invalid key: " << node.value("leftKey").toString();
if(rightKey.first == AT_INVALID)
if ((-1 == leftKey && -1 == leftBtn) qWarning() << "json error: keyMapNodes node invalid key: " << node.value("rightKey").toString();
|| (-1 == rightKey && -1 == rightBtn) if(upKey.first == AT_INVALID)
|| (-1 == upKey && -1 == upBtn) qWarning() << "json error: keyMapNodes node invalid key: " << node.value("upKey").toString();
|| (-1 == downKey && -1 == downBtn) if(downKey.first == AT_INVALID)
) { qWarning() << "json error: keyMapNodes node invalid key: " << node.value("downKey").toString();
qWarning() << "json error: keyMapNodes node invalid key: " << node.value("key").toString();
break; break;
} }
@ -226,41 +182,45 @@ void KeyMap::loadKeyMap(const QString &json)
keyMapNode.steerWheel.pressKeysNum = 0; keyMapNode.steerWheel.pressKeysNum = 0;
keyMapNode.steerWheel.firstPressKey = 0; keyMapNode.steerWheel.firstPressKey = 0;
if (leftKey != -1) { keyMapNode.steerWheel.left = { leftKey.first, leftKey.second, getItemNumber(node, "leftOffset") };
keyMapNode.steerWheel.leftKey = leftKey; keyMapNode.steerWheel.right = { rightKey.first, rightKey.second, getItemNumber(node, "rightOffset") };
} else { keyMapNode.steerWheel.up = { upKey.first, upKey.second, getItemNumber(node, "upOffset") };
keyMapNode.steerWheel.leftKey = leftBtn; keyMapNode.steerWheel.down = { downKey.first, downKey.second, getItemNumber(node, "downOffset") };
}
if (rightKey != -1) { keyMapNode.steerWheel.centerPos = getItemPos(node, "centerPos");
keyMapNode.steerWheel.rightKey = rightKey;
} else {
keyMapNode.steerWheel.rightKey = rightBtn;
}
if (upKey != -1) {
keyMapNode.steerWheel.upKey = upKey;
} else {
keyMapNode.steerWheel.upKey = upBtn;
}
if (downKey != -1) {
keyMapNode.steerWheel.downKey = downKey;
} else {
keyMapNode.steerWheel.downKey = downBtn;
}
keyMapNode.steerWheel.leftOffset = node.value("leftOffset").toDouble();
keyMapNode.steerWheel.rightOffset = node.value("rightOffset").toDouble();
keyMapNode.steerWheel.upOffset = node.value("upOffset").toDouble();
keyMapNode.steerWheel.downOffset = node.value("downOffset").toDouble();
keyMapNode.steerWheel.centerPos = QPointF(node.value("centerPos").toObject().value("x").toDouble(),
node.value("centerPos").toObject().value("y").toDouble());
m_keyMapNodes.push_back(keyMapNode); m_keyMapNodes.push_back(keyMapNode);
} }
break; break;
case KeyMap::KMT_DRAG:
{
// safe check
if(!checkForDrag(node)){
qWarning() << "json error: keyMapNodes node format error";
break;
}
QPair<ActionType, int> key = getItemKey(node, "key");
if(key.first == AT_INVALID){
qWarning() << "json error: keyMapNodes node invalid key: " << node.value("key").toString();
break;
}
KeyMapNode keyMapNode;
keyMapNode.type = type;
keyMapNode.drag.type = key.first;
keyMapNode.drag.key = key.second;
keyMapNode.drag.startPos = getItemPos(node, "startPos");
keyMapNode.drag.endPos = getItemPos(node, "endPos");
m_keyMapNodes.push_back(keyMapNode);
break;
}
default: default:
qWarning() << "json error: keyMapNodes invalid node type:" << node.value("type").toString(); qWarning() << "json error: keyMapNodes invalid node type:" << node.value("type").toString();
break; break;
} }
} }
} }
// this must be called after m_keyMapNodes is stable
makeReverseMap();
qWarning() << "Script updated."; qWarning() << "Script updated.";
parseError: parseError:
@ -272,33 +232,20 @@ parseError:
KeyMap::KeyMapNode& KeyMap::getKeyMapNode(int key) KeyMap::KeyMapNode& KeyMap::getKeyMapNode(int key)
{ {
for (auto& itemNode : m_keyMapNodes) { auto p = rmapKey.value(key, &m_invalidNode);
switch (itemNode.type) { if(p == &m_invalidNode)
case KMT_CLICK: return *rmapMouse.value(key, &m_invalidNode);
if (itemNode.click.keyNode.key == key) { return *p;
return itemNode; }
}
break;
case KMT_CLICK_TWICE:
if (itemNode.clickTwice.keyNode.key == key) {
return itemNode;
}
break;
case KMT_STEER_WHEEL:
if (itemNode.steerWheel.leftKey == key
|| itemNode.steerWheel.rightKey == key
|| itemNode.steerWheel.upKey == key
|| itemNode.steerWheel.downKey == key
) {
return itemNode;
}
break;
default:
break;
}
}
return m_invalidNode; KeyMap::KeyMapNode& KeyMap::getKeyMapNodeKey(int key)
{
return *rmapKey.value(key, &m_invalidNode);
}
KeyMap::KeyMapNode& KeyMap::getKeyMapNodeMouse(int key)
{
return *rmapMouse.value(key, &m_invalidNode);
} }
bool KeyMap::isSwitchOnKeyboard() bool KeyMap::isSwitchOnKeyboard()
@ -320,3 +267,140 @@ bool KeyMap::enableMouseMoveMap()
{ {
return !m_mouseMoveMap.startPos.isNull(); return !m_mouseMoveMap.startPos.isNull();
} }
void KeyMap::makeReverseMap()
{
rmapKey.clear();
rmapMouse.clear();
for(int i = 0 ;i < m_keyMapNodes.size(); ++i) {
auto& node = m_keyMapNodes[i];
switch (node.type) {
case KMT_CLICK:
{
QMultiHash<int, KeyMapNode*>& m = node.click.keyNode.type == AT_KEY ? rmapKey : rmapMouse;
m.insert(node.click.keyNode.key, &node);
}
break;
case KMT_CLICK_TWICE:
{
QMultiHash<int, KeyMapNode*>& m = node.clickTwice.keyNode.type == AT_KEY ? rmapKey : rmapMouse;
m.insert(node.clickTwice.keyNode.key, &node);
}
break;
case KMT_STEER_WHEEL:
{
QMultiHash<int, KeyMapNode*>& ml = node.steerWheel.left.type == AT_KEY ? rmapKey : rmapMouse;
ml.insert(node.steerWheel.left.key, &node);
QMultiHash<int, KeyMapNode*>& mr = node.steerWheel.right.type == AT_KEY ? rmapKey : rmapMouse;
mr.insert(node.steerWheel.right.key, &node);
QMultiHash<int, KeyMapNode*>& mu = node.steerWheel.up.type == AT_KEY ? rmapKey : rmapMouse;
mu.insert(node.steerWheel.up.key, &node);
QMultiHash<int, KeyMapNode*>& md = node.steerWheel.down.type == AT_KEY ? rmapKey : rmapMouse;
md.insert(node.steerWheel.down.key, &node);
}
break;
case KMT_DRAG:
{
QMultiHash<int, KeyMapNode*>& m = node.drag.type == AT_KEY ? rmapKey : rmapMouse;
m.insert(node.drag.key, &node);
}
break;
default:
break;
}
}
}
// ---- check and get of json item ----
bool KeyMap::checkItemKey(const QJsonObject& node, QString name)
{
return node.contains(name) && node.value(name).isString();
}
bool KeyMap::checkItemPos(const QJsonObject& node, QString name)
{
if(node.contains(name) && node.value(name).isObject()){
QJsonObject pos = node.value(name).toObject();
return pos.contains("x") && pos.value("x").isDouble()
&& pos.contains("y") && pos.value("y").isDouble();
}
return false;
}
bool KeyMap::checkItemDouble(const QJsonObject& node, QString name)
{
return node.contains(name) && node.value(name).isDouble();
}
bool KeyMap::checkItemSwitchMap(const QJsonObject& node, QString name)
{
return !node.contains(name) || node.value(name).isBool();
}
KeyMap::KeyMapType KeyMap::getItemType(const QJsonObject& node, QString name)
{
QString value = node.value(name).toString();
return static_cast<KeyMap::KeyMapType>(m_metaEnumKeyMapType.keyToValue(value.toStdString().c_str()));
}
QPair<KeyMap::ActionType, int> KeyMap::getItemKey(const QJsonObject& node, QString name)
{
QString value = node.value(name).toString();
int key = m_metaEnumKey.keyToValue(value.toStdString().c_str());
int btn = m_metaEnumMouseButtons.keyToValue(value.toStdString().c_str());
if(key == -1 && btn == -1){
return {AT_INVALID, -1};
}else if(key != -1){
return {AT_KEY, key};
}else{
return {AT_MOUSE, btn};
}
}
QPointF KeyMap::getItemPos(const QJsonObject& node, QString name)
{
QJsonObject pos = node.value(name).toObject();
return QPointF(pos.value("x").toDouble(), pos.value("y").toDouble());
}
double KeyMap::getItemNumber(const QJsonObject& node, QString name)
{
return node.value(name).toDouble();
}
bool KeyMap::getItemSwitchMap(const QJsonObject& node, QString name)
{
return node.value(name).toBool(false);
}
// ---- check for key-map node ----
bool KeyMap::checkForClick(const QJsonObject& node)
{
return checkItemKey(node, "key") && checkItemPos(node, "pos")
&& checkItemSwitchMap(node, "switchMap");
}
bool KeyMap::checkForClickDouble(const QJsonObject& node)
{
return checkForClick(node);
}
bool KeyMap::checkForSteerWhell(const QJsonObject& node)
{
return checkItemKey(node, "leftKey") && checkItemKey(node, "rightKey")
&& checkItemKey(node, "upKey") && checkItemKey(node, "downKey")
&& checkItemDouble(node, "leftOffset") && checkItemDouble(node, "rightOffset")
&& checkItemDouble(node, "upOffset") && checkItemDouble(node, "downOffset")
&& checkItemPos(node, "centerPos");
}
bool KeyMap::checkForDrag(const QJsonObject& node)
{
return checkItemKey(node, "key")
&& checkItemPos(node, "startPos") && checkItemPos(node, "endPos")
&& checkItemSwitchMap(node, "switchMap");
}

View file

@ -4,7 +4,11 @@
#include <QPointF> #include <QPointF>
#include <QVector> #include <QVector>
#include <QRectF> #include <QRectF>
#include <QPair>
#include <QMetaEnum>
#include <QMultiHash>
class QJsonObject;
class KeyMap : public QObject class KeyMap : public QObject
{ {
@ -15,16 +19,19 @@ public:
KMT_CLICK = 0, KMT_CLICK = 0,
KMT_CLICK_TWICE, KMT_CLICK_TWICE,
KMT_STEER_WHEEL, KMT_STEER_WHEEL,
KMT_DRAG,
}; };
Q_ENUM(KeyMapType) Q_ENUM(KeyMapType)
enum ActionType { enum ActionType {
AT_INVALID = -1,
AT_KEY = 0, AT_KEY = 0,
AT_MOUSE = 1, AT_MOUSE = 1,
}; };
Q_ENUM(ActionType) Q_ENUM(ActionType)
struct KeyNode { struct KeyNode {
ActionType type = AT_INVALID;
int key = Qt::Key_unknown; int key = Qt::Key_unknown;
QPointF pos = QPointF(0, 0); QPointF pos = QPointF(0, 0);
}; };
@ -41,19 +48,14 @@ public:
} clickTwice; } clickTwice;
struct { struct {
// 方向盘矩形中心位置 // 方向盘矩形中心位置
QPointF centerPos = {0.0f, 0.0f}; QPointF centerPos = {0.0, 0.0};
// 方向盘矩形四个方向偏移量 struct DirInfo{
float leftOffset = 0.0f; ActionType type = AT_KEY; // keyboard/mouse
float rightOffset = 0.0f; int key = Qt::Key_unknown; // key/button
float upOffset = 0.0f; double offset = 0.0;
float downOffset = 0.0f; };
DirInfo left, right, up, down;
// 方向盘矩形四个方向按键
int leftKey = Qt::Key_unknown;
int rightKey = Qt::Key_unknown;
int upKey = Qt::Key_unknown;
int downKey = Qt::Key_unknown;
// 辅助变量 // 辅助变量
// 方向键的按下状态 // 方向键的按下状态
@ -66,6 +68,12 @@ public:
// 第一次按下的键 // 第一次按下的键
int firstPressKey = 0; int firstPressKey = 0;
} steerWheel; } steerWheel;
struct {
ActionType type = AT_KEY;
int key = Qt::Key_unknown;
QPointF startPos = QPointF(0, 0);
QPointF endPos = QPointF(0, 0);
} drag;
}; };
KeyMapNode() {} KeyMapNode() {}
~KeyMapNode() {} ~KeyMapNode() {}
@ -81,6 +89,8 @@ public:
void loadKeyMap(const QString &json); void loadKeyMap(const QString &json);
KeyMap::KeyMapNode& getKeyMapNode(int key); KeyMap::KeyMapNode& getKeyMapNode(int key);
KeyMap::KeyMapNode& getKeyMapNodeKey(int key);
KeyMap::KeyMapNode& getKeyMapNodeMouse(int key);
bool isSwitchOnKeyboard(); bool isSwitchOnKeyboard();
int getSwitchKey(); int getSwitchKey();
MouseMoveMap getMouseMoveMap(); MouseMoveMap getMouseMoveMap();
@ -88,6 +98,28 @@ public:
static const QString& getKeyMapPath(); static const QString& getKeyMapPath();
private:
// set up the reverse map from key/event event to keyMapNode
void makeReverseMap();
// parse json of the mapping script
bool checkItemKey(const QJsonObject& node, QString name="key");
bool checkItemPos(const QJsonObject& node, QString name="pos");
bool checkItemDouble(const QJsonObject& node, QString name);
bool checkItemSwitchMap(const QJsonObject& node, QString name="switchMap");
KeyMapType getItemType(const QJsonObject& node, QString name="type");
QPair<ActionType, int> getItemKey(const QJsonObject& node, QString name="key");
QPointF getItemPos(const QJsonObject& node, QString name="pos");
double getItemNumber(const QJsonObject& node, QString name);
bool getItemSwitchMap(const QJsonObject& node, QString name="switchMap");
private:
bool checkForClick(const QJsonObject& node);
bool checkForClickDouble(const QJsonObject& node);
bool checkForSteerWhell(const QJsonObject& node);
bool checkForDrag(const QJsonObject& node);
private: private:
QVector<KeyMapNode> m_keyMapNodes; QVector<KeyMapNode> m_keyMapNodes;
KeyMapNode m_invalidNode; KeyMapNode m_invalidNode;
@ -95,6 +127,14 @@ private:
int m_switchKey = Qt::Key_QuoteLeft; int m_switchKey = Qt::Key_QuoteLeft;
MouseMoveMap m_mouseMoveMap; MouseMoveMap m_mouseMoveMap;
static QString s_keyMapPath; static QString s_keyMapPath;
// mapping of key/mouse event name to index
QMetaEnum m_metaEnumKey = QMetaEnum::fromType<Qt::Key>();
QMetaEnum m_metaEnumMouseButtons = QMetaEnum::fromType<Qt::MouseButtons>();
QMetaEnum m_metaEnumKeyMapType = QMetaEnum::fromType<KeyMap::KeyMapType>();
// reverse map of key/mouse event
QMultiHash<int, KeyMapNode*> rmapKey;
QMultiHash<int, KeyMapNode*> rmapMouse;
}; };
#endif // KEYMAP_H #endif // KEYMAP_H