Merge pull request #263 from barry-ran/dev

Dev
This commit is contained in:
Barry 2020-08-02 13:39:55 +08:00 committed by GitHub
commit e499cf946b
13 changed files with 231 additions and 14 deletions

View file

@ -56,6 +56,15 @@ void Controller::updateScript(QString gameScript)
connect(m_inputConvert, &InputConvertBase::grabCursor, this, &Controller::grabCursor); connect(m_inputConvert, &InputConvertBase::grabCursor, this, &Controller::grabCursor);
} }
bool Controller::isCurrentCustomKeymap()
{
if (!m_inputConvert) {
return false;
}
return m_inputConvert->isCurrentCustomKeymap();
}
void Controller::onPostBackOrScreenOn() void Controller::onPostBackOrScreenOn()
{ {
ControlMsg *controlMsg = new ControlMsg(ControlMsg::CMT_BACK_OR_SCREEN_ON); ControlMsg *controlMsg = new ControlMsg(ControlMsg::CMT_BACK_OR_SCREEN_ON);

View file

@ -21,6 +21,7 @@ public:
void test(QRect rc); void test(QRect rc);
void updateScript(QString gameScript = ""); void updateScript(QString gameScript = "");
bool isCurrentCustomKeymap();
public slots: public slots:
void onPostGoBack(); void onPostGoBack();

View file

@ -21,6 +21,10 @@ public:
virtual void mouseEvent(const QMouseEvent *from, const QSize &frameSize, const QSize &showSize) = 0; virtual void mouseEvent(const QMouseEvent *from, const QSize &frameSize, const QSize &showSize) = 0;
virtual void wheelEvent(const QWheelEvent *from, const QSize &frameSize, const QSize &showSize) = 0; virtual void wheelEvent(const QWheelEvent *from, const QSize &frameSize, const QSize &showSize) = 0;
virtual void keyEvent(const QKeyEvent *from, const QSize &frameSize, const QSize &showSize) = 0; virtual void keyEvent(const QKeyEvent *from, const QSize &frameSize, const QSize &showSize) = 0;
virtual bool isCurrentCustomKeymap()
{
return false;
};
signals: signals:
void grabCursor(bool grab); void grabCursor(bool grab);

View file

@ -78,7 +78,7 @@ void InputConvertGame::keyEvent(const QKeyEvent *from, const QSize &frameSize, c
} }
// small eyes // small eyes
if (from->key() == m_keyMap.getMouseMoveMap().data.mouseMove.smallEyes.key) { if (m_keyMap.isValidMouseMoveMap() && from->key() == m_keyMap.getMouseMoveMap().data.mouseMove.smallEyes.key) {
m_ctrlMouseMove.smallEyes = (QEvent::KeyPress == from->type()); m_ctrlMouseMove.smallEyes = (QEvent::KeyPress == from->type());
if (QEvent::KeyPress == from->type()) { if (QEvent::KeyPress == from->type()) {
@ -110,6 +110,9 @@ void InputConvertGame::keyEvent(const QKeyEvent *from, const QSize &frameSize, c
case KeyMap::KMT_CLICK_TWICE: case KeyMap::KMT_CLICK_TWICE:
processKeyClick(node.data.clickTwice.keyNode.pos, true, false, from); processKeyClick(node.data.clickTwice.keyNode.pos, true, false, from);
return; return;
case KeyMap::KMT_CLICK_MULTI:
processKeyClickMulti(node.data.clickMulti.keyNode.delayClickNodes, node.data.clickMulti.keyNode.delayClickNodesCount, from);
return;
case KeyMap::KMT_DRAG: case KeyMap::KMT_DRAG:
processKeyDrag(node.data.drag.keyNode.pos, node.data.drag.keyNode.extendPos, from); processKeyDrag(node.data.drag.keyNode.pos, node.data.drag.keyNode.extendPos, from);
return; return;
@ -121,6 +124,11 @@ void InputConvertGame::keyEvent(const QKeyEvent *from, const QSize &frameSize, c
} }
} }
bool InputConvertGame::isCurrentCustomKeymap()
{
return m_gameMap;
}
void InputConvertGame::loadKeyMap(const QString &json) void InputConvertGame::loadKeyMap(const QString &json)
{ {
m_keyMap.loadKeyMap(json); m_keyMap.loadKeyMap(json);
@ -164,8 +172,15 @@ void InputConvertGame::sendTouchEvent(int id, QPointF pos, AndroidMotioneventAct
if (!controlMsg) { if (!controlMsg) {
return; return;
} }
controlMsg->setInjectTouchMsgData(
static_cast<quint64>(id), action, static_cast<AndroidMotioneventButtons>(0), QRect(calcFrameAbsolutePos(pos).toPoint(), m_frameSize), 1.0f); QPoint absolutePos = calcFrameAbsolutePos(pos).toPoint();
static QPoint lastAbsolutePos = absolutePos;
if (AMOTION_EVENT_ACTION_MOVE == action && lastAbsolutePos == absolutePos) {
return;
}
lastAbsolutePos = absolutePos;
controlMsg->setInjectTouchMsgData(static_cast<quint64>(id), action, static_cast<AndroidMotioneventButtons>(0), QRect(absolutePos, m_frameSize), 1.0f);
sendControlMsg(controlMsg); sendControlMsg(controlMsg);
} }
@ -302,6 +317,34 @@ void InputConvertGame::processKeyClick(const QPointF &clickPos, bool clickTwice,
} }
} }
void InputConvertGame::processKeyClickMulti(const KeyMap::DelayClickNode *nodes, const int count, const QKeyEvent *from)
{
if (QEvent::KeyPress != from->type()) {
return;
}
int key = from->key();
int delay = 0;
QPointF clickPos;
for (int i = 0; i < count; i++) {
delay += nodes[i].delay;
clickPos = nodes[i].pos;
QTimer::singleShot(delay, this, [this, key, clickPos]() {
int id = attachTouchID(key);
sendTouchDownEvent(id, clickPos);
});
// Don't up it too fast
delay += 20;
QTimer::singleShot(delay, this, [this, key, clickPos]() {
int id = getTouchID(key);
sendTouchUpEvent(id, clickPos);
detachTouchID(key);
});
}
}
void InputConvertGame::processKeyDrag(const QPointF &startPos, QPointF endPos, const QKeyEvent *from) void InputConvertGame::processKeyDrag(const QPointF &startPos, QPointF endPos, const QKeyEvent *from)
{ {
if (QEvent::KeyPress == from->type()) { if (QEvent::KeyPress == from->type()) {
@ -361,8 +404,8 @@ bool InputConvertGame::processMouseMove(const QMouseEvent *from)
m_ctrlMouseMove.lastConverPos.setX(m_ctrlMouseMove.lastConverPos.x() + distance.x() / m_showSize.width()); m_ctrlMouseMove.lastConverPos.setX(m_ctrlMouseMove.lastConverPos.x() + distance.x() / m_showSize.width());
m_ctrlMouseMove.lastConverPos.setY(m_ctrlMouseMove.lastConverPos.y() + distance.y() / m_showSize.height()); m_ctrlMouseMove.lastConverPos.setY(m_ctrlMouseMove.lastConverPos.y() + distance.y() / m_showSize.height());
if (m_ctrlMouseMove.lastConverPos.x() < 0.1 || m_ctrlMouseMove.lastConverPos.x() > 0.8 || m_ctrlMouseMove.lastConverPos.y() < 0.1 if (m_ctrlMouseMove.lastConverPos.x() < 0.05 || m_ctrlMouseMove.lastConverPos.x() > 0.95 || m_ctrlMouseMove.lastConverPos.y() < 0.05
|| m_ctrlMouseMove.lastConverPos.y() > 0.8) { || m_ctrlMouseMove.lastConverPos.y() > 0.95) {
if (m_ctrlMouseMove.smallEyes) { if (m_ctrlMouseMove.smallEyes) {
m_processMouseMove = false; m_processMouseMove = false;
int delay = 30; int delay = 30;
@ -442,7 +485,7 @@ void InputConvertGame::mouseMoveStopTouch()
void InputConvertGame::startMouseMoveTimer() void InputConvertGame::startMouseMoveTimer()
{ {
stopMouseMoveTimer(); stopMouseMoveTimer();
m_ctrlMouseMove.timer = startTimer(1000); m_ctrlMouseMove.timer = startTimer(500);
} }
void InputConvertGame::stopMouseMoveTimer() void InputConvertGame::stopMouseMoveTimer()
@ -456,6 +499,7 @@ void InputConvertGame::stopMouseMoveTimer()
bool InputConvertGame::switchGameMap() bool InputConvertGame::switchGameMap()
{ {
m_gameMap = !m_gameMap; m_gameMap = !m_gameMap;
qInfo() << tr("current keymap mode: %1").arg(m_gameMap ? tr("custom") : tr("normal"));
if (!m_keyMap.isValidMouseMoveMap()) { if (!m_keyMap.isValidMouseMoveMap()) {
return m_gameMap; return m_gameMap;

View file

@ -17,6 +17,7 @@ public:
virtual void mouseEvent(const QMouseEvent *from, const QSize &frameSize, const QSize &showSize); virtual void mouseEvent(const QMouseEvent *from, const QSize &frameSize, const QSize &showSize);
virtual void wheelEvent(const QWheelEvent *from, const QSize &frameSize, const QSize &showSize); virtual void wheelEvent(const QWheelEvent *from, const QSize &frameSize, const QSize &showSize);
virtual void keyEvent(const QKeyEvent *from, const QSize &frameSize, const QSize &showSize); virtual void keyEvent(const QKeyEvent *from, const QSize &frameSize, const QSize &showSize);
virtual bool isCurrentCustomKeymap();
void loadKeyMap(const QString &json); void loadKeyMap(const QString &json);
@ -40,6 +41,9 @@ protected:
// click // click
void processKeyClick(const QPointF &clickPos, bool clickTwice, bool switchMap, const QKeyEvent *from); void processKeyClick(const QPointF &clickPos, bool clickTwice, bool switchMap, const QKeyEvent *from);
// click mutil
void processKeyClickMulti(const KeyMap::DelayClickNode *nodes, const int count, const QKeyEvent *from);
// drag // drag
void processKeyDrag(const QPointF &startPos, QPointF endPos, const QKeyEvent *from); void processKeyDrag(const QPointF &startPos, QPointF endPos, const QKeyEvent *from);

View file

@ -175,6 +175,41 @@ void KeyMap::loadKeyMap(const QString &json)
keyMapNode.data.click.switchMap = getItemBool(node, "switchMap"); keyMapNode.data.click.switchMap = getItemBool(node, "switchMap");
m_keyMapNodes.push_back(keyMapNode); m_keyMapNodes.push_back(keyMapNode);
} break; } break;
case KeyMap::KMT_CLICK_MULTI: {
// safe check
if (!checkForClickMulti(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.data.clickMulti.keyNode.type = key.first;
keyMapNode.data.clickMulti.keyNode.key = key.second;
QJsonArray clickNodes = node.value("clickNodes").toArray();
QJsonObject clickNode;
keyMapNode.data.clickMulti.keyNode.delayClickNodesCount = 0;
for (int i = 0; i < clickNodes.size(); i++) {
if (i >= MAX_DELAY_CLICK_NODES) {
qInfo() << "clickNodes too much, up to " << MAX_DELAY_CLICK_NODES;
break;
}
clickNode = clickNodes.at(i).toObject();
DelayClickNode delayClickNode;
delayClickNode.delay = getItemDouble(clickNode, "delay");
delayClickNode.pos = getItemPos(clickNode, "pos");
keyMapNode.data.clickMulti.keyNode.delayClickNodes[i] = delayClickNode;
keyMapNode.data.clickMulti.keyNode.delayClickNodesCount++;
}
m_keyMapNodes.push_back(keyMapNode);
} break;
case KeyMap::KMT_STEER_WHEEL: { case KeyMap::KMT_STEER_WHEEL: {
// safe check // safe check
if (!checkForSteerWhell(node)) { if (!checkForSteerWhell(node)) {
@ -242,7 +277,7 @@ void KeyMap::loadKeyMap(const QString &json)
} }
// this must be called after m_keyMapNodes is stable // this must be called after m_keyMapNodes is stable
makeReverseMap(); makeReverseMap();
qInfo() << "Script updated."; qInfo() << tr("Script updated, current keymap mode:normal, Press ~ key to switch keymap mode");
parseError: parseError:
if (!errorString.isEmpty()) { if (!errorString.isEmpty()) {
@ -310,6 +345,10 @@ void KeyMap::makeReverseMap()
QMultiHash<int, KeyMapNode *> &m = node.data.clickTwice.keyNode.type == AT_KEY ? m_rmapKey : m_rmapMouse; QMultiHash<int, KeyMapNode *> &m = node.data.clickTwice.keyNode.type == AT_KEY ? m_rmapKey : m_rmapMouse;
m.insert(node.data.clickTwice.keyNode.key, &node); m.insert(node.data.clickTwice.keyNode.key, &node);
} break; } break;
case KMT_CLICK_MULTI: {
QMultiHash<int, KeyMapNode *> &m = node.data.clickMulti.keyNode.type == AT_KEY ? m_rmapKey : m_rmapMouse;
m.insert(node.data.clickMulti.keyNode.key, &node);
} break;
case KMT_STEER_WHEEL: { case KMT_STEER_WHEEL: {
QMultiHash<int, KeyMapNode *> &ml = node.data.steerWheel.left.type == AT_KEY ? m_rmapKey : m_rmapMouse; QMultiHash<int, KeyMapNode *> &ml = node.data.steerWheel.left.type == AT_KEY ? m_rmapKey : m_rmapMouse;
ml.insert(node.data.steerWheel.left.key, &node); ml.insert(node.data.steerWheel.left.key, &node);
@ -410,6 +449,45 @@ bool KeyMap::checkForClick(const QJsonObject &node)
return checkForClickTwice(node) && checkItemBool(node, "switchMap"); return checkForClickTwice(node) && checkItemBool(node, "switchMap");
} }
bool KeyMap::checkForClickMulti(const QJsonObject &node)
{
bool ret = true;
if (!node.contains("clickNodes") || !node.value("clickNodes").isArray()) {
qWarning("json error: no find clickNodes");
return false;
}
QJsonArray clickNodes = node.value("clickNodes").toArray();
QJsonObject clickNode;
int size = clickNodes.size();
if (0 == size) {
qWarning("json error: clickNodes is empty");
return false;
}
for (int i = 0; i < size; i++) {
if (!clickNodes.at(i).isObject()) {
qWarning("json error: clickNodes node must be json object");
ret = false;
break;
}
clickNode = clickNodes.at(i).toObject();
if (!checkForDelayClickNode(clickNode)) {
ret = false;
break;
}
}
return ret;
}
bool KeyMap::checkForDelayClickNode(const QJsonObject &node)
{
return checkItemPos(node, "pos") && checkItemDouble(node, "delay");
}
bool KeyMap::checkForClickTwice(const QJsonObject &node) bool KeyMap::checkForClickTwice(const QJsonObject &node)
{ {
return checkItemString(node, "key") && checkItemPos(node, "pos"); return checkItemString(node, "key") && checkItemPos(node, "pos");

View file

@ -9,6 +9,8 @@
#include <QRectF> #include <QRectF>
#include <QVector> #include <QVector>
#define MAX_DELAY_CLICK_NODES 50
class KeyMap : public QObject class KeyMap : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -18,6 +20,7 @@ public:
KMT_INVALID = -1, KMT_INVALID = -1,
KMT_CLICK = 0, KMT_CLICK = 0,
KMT_CLICK_TWICE, KMT_CLICK_TWICE,
KMT_CLICK_MULTI,
KMT_STEER_WHEEL, KMT_STEER_WHEEL,
KMT_DRAG, KMT_DRAG,
KMT_MOUSE_MOVE KMT_MOUSE_MOVE
@ -32,13 +35,21 @@ public:
}; };
Q_ENUM(ActionType) Q_ENUM(ActionType)
struct DelayClickNode
{
int delay = 0;
QPointF pos = QPointF(0, 0);
};
struct KeyNode struct KeyNode
{ {
ActionType type = AT_INVALID; ActionType type = AT_INVALID;
int key = Qt::Key_unknown; int key = Qt::Key_unknown;
QPointF pos = QPointF(0, 0); // normal key QPointF pos = QPointF(0, 0); // normal key
QPointF extendPos = QPointF(0, 0); // for drag QPointF extendPos = QPointF(0, 0); // for drag
double extendOffset = 0.0; // for steerWheel double extendOffset = 0.0; // for steerWheel
DelayClickNode delayClickNodes[MAX_DELAY_CLICK_NODES]; // for multi clicks
int delayClickNodesCount = 0;
KeyNode( KeyNode(
ActionType type = AT_INVALID, ActionType type = AT_INVALID,
@ -66,6 +77,10 @@ public:
KeyNode keyNode; KeyNode keyNode;
} clickTwice; } clickTwice;
struct struct
{
KeyNode keyNode;
} clickMulti;
struct
{ {
QPointF centerPos = { 0.0, 0.0 }; QPointF centerPos = { 0.0, 0.0 };
KeyNode left, right, up, down; KeyNode left, right, up, down;
@ -83,6 +98,7 @@ public:
DATA() {} DATA() {}
~DATA() {} ~DATA() {}
} data; } data;
KeyMapNode() {} KeyMapNode() {}
~KeyMapNode() {} ~KeyMapNode() {}
}; };
@ -116,6 +132,8 @@ private:
// safe check for KeyMapNode // safe check for KeyMapNode
bool checkForClick(const QJsonObject &node); bool checkForClick(const QJsonObject &node);
bool checkForClickMulti(const QJsonObject &node);
bool checkForDelayClickNode(const QJsonObject &node);
bool checkForClickTwice(const QJsonObject &node); bool checkForClickTwice(const QJsonObject &node);
bool checkForSteerWhell(const QJsonObject &node); bool checkForSteerWhell(const QJsonObject &node);
bool checkForDrag(const QJsonObject &node); bool checkForDrag(const QJsonObject &node);

View file

@ -339,6 +339,14 @@ Device::GroupControlState Device::controlState()
return m_controlState; return m_controlState;
} }
bool Device::isCurrentCustomKeymap()
{
if (!m_controller) {
return false;
}
return m_controller->isCurrentCustomKeymap();
}
bool Device::saveFrame(const AVFrame *frame) bool Device::saveFrame(const AVFrame *frame)
{ {
if (!frame) { if (!frame) {

View file

@ -56,6 +56,8 @@ public:
void updateScript(QString script); void updateScript(QString script);
Device::GroupControlState controlState(); Device::GroupControlState controlState();
bool isCurrentCustomKeymap();
signals: signals:
void deviceDisconnect(QString serial); void deviceDisconnect(QString serial);

View file

@ -501,7 +501,7 @@ void VideoForm::setDevice(Device *device)
void VideoForm::mousePressEvent(QMouseEvent *event) void VideoForm::mousePressEvent(QMouseEvent *event)
{ {
if (event->button() == Qt::MiddleButton) { if (event->button() == Qt::MiddleButton) {
if (m_device) { if (m_device && !m_device->isCurrentCustomKeymap()) {
emit m_device->postGoHome(); emit m_device->postGoHome();
} }
} }
@ -580,7 +580,7 @@ void VideoForm::mouseDoubleClickEvent(QMouseEvent *event)
} }
} }
if (event->button() == Qt::RightButton && m_device) { if (event->button() == Qt::RightButton && m_device && !m_device->isCurrentCustomKeymap()) {
emit m_device->postBackOrScreenOn(); emit m_device->postBackOrScreenOn();
} }
@ -701,7 +701,7 @@ void VideoForm::dropEvent(QDropEvent *event)
const QMimeData *qm = event->mimeData(); const QMimeData *qm = event->mimeData();
QList<QUrl> urls = qm->urls(); QList<QUrl> urls = qm->urls();
for (const QUrl& url : urls) { for (const QUrl &url : urls) {
QString file = url.toLocalFile(); QString file = url.toLocalFile();
QFileInfo fileInfo(file); QFileInfo fileInfo(file);

View file

@ -35,6 +35,7 @@ There are several types of key mapping as follows:
-type The type of key mapping, each element in keyMapNodes needs to be specified, and can be of the following types: -type The type of key mapping, each element in keyMapNodes needs to be specified, and can be of the following types:
-KMT_CLICK Ordinary click, key press simulates finger press, key lift simulates finger lift -KMT_CLICK Ordinary click, key press simulates finger press, key lift simulates finger lift
-KMT_CLICK_TWICE Double click, key press simulates finger press and then lift, key lift simulates finger press and then lift -KMT_CLICK_TWICE Double click, key press simulates finger press and then lift, key lift simulates finger press and then lift
- KMT_CLICK_MULTI Click multiple times. According to the delay and pos in the clickNodes array, press one key to simulate touching multiple positions
-KMT_DRAG drag and drop, the key press is simulated as a finger press and drag a distance, the key lift is simulated as a finger lift -KMT_DRAG drag and drop, the key press is simulated as a finger press and drag a distance, the key lift is simulated as a finger lift
-KMT_STEER_WHEEL steering wheel mapping, which is dedicated to the mapping of the steering wheel for moving characters in FPS games, requires 4 buttons to cooperate. -KMT_STEER_WHEEL steering wheel mapping, which is dedicated to the mapping of the steering wheel for moving characters in FPS games, requires 4 buttons to cooperate.
@ -47,7 +48,11 @@ Description of the unique attributes of different key mapping types:
-KMT_CLICK_TWICE -KMT_CLICK_TWICE
-key The key code to be mapped -key The key code to be mapped
-pos simulates the location of the touch -pos Simulates the location of the touch
-KMT_CLICK_MULTI
-delay Delay `delay` ms before simulating touch
-pos Simulates the location of the touch
-KMT_DRAG -KMT_DRAG
-key The key code to be mapped -key The key code to be mapped

View file

@ -35,6 +35,7 @@
- type 按键映射的类型每个keyMapNodes中的元素都需要指明可以是如下类型 - type 按键映射的类型每个keyMapNodes中的元素都需要指明可以是如下类型
- KMT_CLICK 普通点击,按键按下模拟为手指按下,按键抬起模拟为手指抬起 - KMT_CLICK 普通点击,按键按下模拟为手指按下,按键抬起模拟为手指抬起
- KMT_CLICK_TWICE 两次点击,按键按下模拟为手指按下再抬起,按键抬起模拟为手指按下再抬起 - KMT_CLICK_TWICE 两次点击,按键按下模拟为手指按下再抬起,按键抬起模拟为手指按下再抬起
- KMT_CLICK_MULTI 多次点击根据clickNodes数组中的delay和pos实现一个按键多次点击
- KMT_DRAG 拖拽,按键按下模拟为手指按下并拖动一段距离,按键抬起模拟为手指抬起 - KMT_DRAG 拖拽,按键按下模拟为手指按下并拖动一段距离,按键抬起模拟为手指抬起
- KMT_STEER_WHEEL 方向盘映射专用于FPS游戏中移动人物脚步的方向盘的映射需要4个按键来配合。 - KMT_STEER_WHEEL 方向盘映射专用于FPS游戏中移动人物脚步的方向盘的映射需要4个按键来配合。
@ -49,6 +50,10 @@
- key 要映射的按键码 - key 要映射的按键码
- pos 模拟触摸的位置 - pos 模拟触摸的位置
- KMT_CLICK_MULTI
- delay 延迟delay毫秒以后再模拟触摸
- pos 模拟触摸的位置
- KMT_DRAG - KMT_DRAG
- key 要映射的按键码 - key 要映射的按键码
- startPos 模拟触摸拖动的开始位置 - startPos 模拟触摸拖动的开始位置

39
keymap/test.json Normal file
View file

@ -0,0 +1,39 @@
{
"switchKey": "Key_QuoteLeft",
"keyMapNodes": [
{
"comment": "测试一键多点",
"type": "KMT_CLICK_MULTI",
"key": "Key_Space",
"clickNodes": [
{
"delay": 500,
"pos": {
"x": 0.5,
"y": 0.5
}
},
{
"delay": 500,
"pos": {
"x": 0.8,
"y": 0.8
}
}
]
},
{
"comment": "测试拖拽",
"type": "KMT_DRAG",
"key": "Key_Up",
"startPos": {
"x": 0.5,
"y": 0.7
},
"endPos": {
"x": 0.5,
"y": 0.3
}
}
]
}