From a6c1f3e8ffdc36c9591dac7651303de446bdd86a Mon Sep 17 00:00:00 2001 From: Cristian Luis Duarte Date: Fri, 31 Aug 2018 23:02:38 -0300 Subject: [PATCH] Android - Handshake - Generic button manager + RB using it --- .../TouchscreenVirtualPadDevice.cpp | 220 ++++++++++++++---- .../TouchscreenVirtualPadDevice.h | 63 ++++- 2 files changed, 226 insertions(+), 57 deletions(-) diff --git a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp index 48d2555626..eeaa463159 100644 --- a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp @@ -96,6 +96,13 @@ void TouchscreenVirtualPadDevice::setupControlsPositions(VirtualPad::Manager& vi // RB button (use same size as jump) _rbButtonPosition = glm::vec2( eventScreen->availableSize().width() - rightMargin - jumpBtnPixelSize, eventScreen->availableSize().height() - 2 * bottomMargin - 3 * _rbButtonRadius - _extraBottomMargin); virtualPadManager.setRbButtonPosition(_rbButtonPosition); + + // Avoid generating buttons in portrait mode + if ( eventScreen->availableSize().width() > eventScreen->availableSize().height() && _buttonsManager.buttonsCount() == 0) { + //_buttonsManager.addButton(TouchscreenButton(JUMP_BUTTON_PRESS, JUMP, _jumpButtonRadius, _jumpButtonPosition, _inputDevice )); + _buttonsManager.addButton(TouchscreenButton(RB, RB_BUTTON, _rbButtonRadius, _rbButtonPosition, _inputDevice )); + } + } float clip(float n, float lower, float upper) { @@ -241,7 +248,7 @@ void TouchscreenVirtualPadDevice::touchEndEvent(const QTouchEvent* event) { moveTouchEnd(); viewTouchEnd(); jumpTouchEnd(); - rbTouchEnd(); + _buttonsManager.endTouchForAll(); return; } // touch end here is a big reset -> resets both pads @@ -251,7 +258,7 @@ void TouchscreenVirtualPadDevice::touchEndEvent(const QTouchEvent* event) { moveTouchEnd(); viewTouchEnd(); jumpTouchEnd(); - rbTouchEnd(); + _buttonsManager.endTouchForAll(); _inputDevice->_axisStateMap.clear(); _inputDevice->_buttonPressedMap.clear(); } @@ -288,13 +295,14 @@ void TouchscreenVirtualPadDevice::touchUpdateEvent(const QTouchEvent* event) { bool moveTouchFound = false; bool viewTouchFound = false; bool jumpTouchFound = false; - bool rbTouchFound = false; int idxMoveStartingPointCandidate = -1; int idxViewStartingPointCandidate = -1; int idxJumpStartingPointCandidate = -1; int idxRbStartingPointCandidate = -1; + _buttonsManager.resetEventValues(); + glm::vec2 thisPoint; int thisPointId; std::map unusedTouchesInEvent; @@ -325,10 +333,7 @@ void TouchscreenVirtualPadDevice::touchUpdateEvent(const QTouchEvent* event) { continue; } - if (!rbTouchFound && _rbHasValidTouch && _rbCurrentTouchId == thisPointId) { - // valid if it's an ongoing touch - rbTouchFound = true; - rbTouchUpdate(thisPoint); + if (_buttonsManager.processOngoingTouch(thisPoint, thisPointId)) { continue; } @@ -350,9 +355,7 @@ void TouchscreenVirtualPadDevice::touchUpdateEvent(const QTouchEvent* event) { continue; } - if (!rbTouchFound && idxRbStartingPointCandidate == -1 && rbTouchBeginIsValid(thisPoint) && - (!_unusedTouches.count(thisPointId) || _unusedTouches[thisPointId] == RB_BUTTON )) { - idxRbStartingPointCandidate = i; + if (_buttonsManager.findStartingTouchPointCandidate(thisPoint, thisPointId, i, _unusedTouches)) { continue; } @@ -362,8 +365,8 @@ void TouchscreenVirtualPadDevice::touchUpdateEvent(const QTouchEvent* event) { unusedTouchesInEvent[thisPointId] = JUMP; } else if (viewTouchBeginIsValid(thisPoint)) { unusedTouchesInEvent[thisPointId] = VIEW; - } else if (rbTouchBeginIsValid(thisPoint)) { - unusedTouchesInEvent[thisPointId] = RB_BUTTON; + } else { + _buttonsManager.saveUnusedTouches(unusedTouchesInEvent, thisPoint, thisPointId); } } @@ -405,24 +408,13 @@ void TouchscreenVirtualPadDevice::touchUpdateEvent(const QTouchEvent* event) { } } } - if (!rbTouchFound) { - if (idxRbStartingPointCandidate != -1) { - _rbCurrentTouchId = tPoints[idxRbStartingPointCandidate].id(); - _unusedTouches.erase(_rbCurrentTouchId); - thisPoint.x = tPoints[idxRbStartingPointCandidate].pos().x(); - thisPoint.y = tPoints[idxRbStartingPointCandidate].pos().y(); - rbTouchBegin(thisPoint); - } else { - if (_rbHasValidTouch) { - rbTouchEnd(); - } - } - } + + _buttonsManager.processBeginOrEnd(thisPoint, tPoints, _unusedTouches); } bool TouchscreenVirtualPadDevice::viewTouchBeginIsValid(glm::vec2 touchPoint) { - return !moveTouchBeginIsValid(touchPoint) && !jumpTouchBeginIsValid(touchPoint) && !rbTouchBeginIsValid(touchPoint); + return !moveTouchBeginIsValid(touchPoint) && !jumpTouchBeginIsValid(touchPoint) && _buttonsManager.touchBeginInvalidForAllButtons(touchPoint); } bool TouchscreenVirtualPadDevice::moveTouchBeginIsValid(glm::vec2 touchPoint) { @@ -459,29 +451,6 @@ void TouchscreenVirtualPadDevice::jumpTouchEnd() { } } -bool TouchscreenVirtualPadDevice::rbTouchBeginIsValid(glm::vec2 touchPoint) { - return glm::distance2(touchPoint, _rbButtonPosition) < _rbButtonRadius * _rbButtonRadius; -} - -void TouchscreenVirtualPadDevice::rbTouchBegin(glm::vec2 touchPoint) { - auto& virtualPadManager = VirtualPad::Manager::instance(); - if (virtualPadManager.isEnabled() && !virtualPadManager.isHidden()) { - _rbHasValidTouch = true; - - _inputDevice->_buttonPressedMap.insert(TouchButtonChannel::RB); - } -} - -void TouchscreenVirtualPadDevice::rbTouchUpdate(glm::vec2 touchPoint) {} - -void TouchscreenVirtualPadDevice::rbTouchEnd() { - if (_rbHasValidTouch) { - _rbHasValidTouch = false; - - _inputDevice->_buttonPressedMap.erase(TouchButtonChannel::RB); - } -} - void TouchscreenVirtualPadDevice::moveTouchBegin(glm::vec2 touchPoint) { auto& virtualPadManager = VirtualPad::Manager::instance(); if (virtualPadManager.isEnabled() && !virtualPadManager.isHidden()) { @@ -566,3 +535,156 @@ QString TouchscreenVirtualPadDevice::InputDevice::getDefaultMappingConfig() cons static const QString MAPPING_JSON = PathUtils::resourcesPath() + "/controllers/touchscreenvirtualpad.json"; return MAPPING_JSON; } + +TouchscreenVirtualPadDevice::TouchscreenButton::TouchscreenButton( + TouchscreenVirtualPadDevice::TouchButtonChannel channelIn, + TouchscreenVirtualPadDevice::TouchType touchTypeIn, float buttonRadiusIn, + glm::vec2 buttonPositionIn, std::shared_ptr inputDeviceIn) : + channel(channelIn), + touchType(touchTypeIn), + buttonRadius(buttonRadiusIn), + buttonPosition(buttonPositionIn), + _inputDevice(inputDeviceIn) +{ +} + +void TouchscreenVirtualPadDevice::TouchscreenButton::touchBegin(glm::vec2 touchPoint) { + auto& virtualPadManager = VirtualPad::Manager::instance(); + if (virtualPadManager.isEnabled() && !virtualPadManager.isHidden()) { + hasValidTouch = true; + + _inputDevice->_buttonPressedMap.insert(channel); + } +} + +void TouchscreenVirtualPadDevice::TouchscreenButton::touchUpdate(glm::vec2 touchPoint) { + +} + +void TouchscreenVirtualPadDevice::TouchscreenButton::touchEnd() { + if (hasValidTouch) { + hasValidTouch = false; + + _inputDevice->_buttonPressedMap.erase(channel); + } +} + +bool TouchscreenVirtualPadDevice::TouchscreenButton::touchBeginIsValid(glm::vec2 touchPoint) { + qDebug() << "[HANDSHAKE] isValid " << (glm::distance2(touchPoint, buttonPosition) < buttonRadius * buttonRadius) << + " dist2 " << glm::distance2(touchPoint, buttonPosition) << " vs " << buttonRadius * buttonRadius; + return glm::distance2(touchPoint, buttonPosition) < buttonRadius * buttonRadius; +} + +void TouchscreenVirtualPadDevice::TouchscreenButton::resetEventValues() { + _candidatePointIdx = -1; + _found = false; +} + +TouchscreenVirtualPadDevice::TouchscreenButtonsManager::TouchscreenButtonsManager() {} + +void TouchscreenVirtualPadDevice::TouchscreenButtonsManager::addButton( + TouchscreenVirtualPadDevice::TouchscreenButton button) { + buttons.push_back(button); +} + +void TouchscreenVirtualPadDevice::TouchscreenButtonsManager::resetEventValues() { + for(int i = 0; i < buttons.size(); i++) { + TouchscreenButton &button = buttons[i]; + button.resetEventValues(); + } +} + +bool +TouchscreenVirtualPadDevice::TouchscreenButtonsManager::processOngoingTouch(glm::vec2 thisPoint, + int thisPointId) { + for(int i = 0; i < buttons.size(); i++) { + TouchscreenButton &button = buttons[i]; + + if (!button._found && button.hasValidTouch && button.currentTouchId == thisPointId) { + // valid if it's an ongoing touch + button._found = true; + button.touchUpdate(thisPoint); + return true; + } + } + return false; + +} + +bool TouchscreenVirtualPadDevice::TouchscreenButtonsManager::findStartingTouchPointCandidate( + glm::vec2 thisPoint, int thisPointId, int thisPointIdx, std::map &globalUnusedTouches) { + + for(int i = 0; i < buttons.size(); i++) { + TouchscreenButton &button = buttons[i]; + qDebug() << "[HANDSHAKE] !button._found && button._candidatePointIdx == -1 " << (!button._found && button._candidatePointIdx == -1); + qDebug() << "[HANDSHAKE] button.touchBeginIsValid(thisPoint) " << (button.touchBeginIsValid(thisPoint)); + qDebug() << "[HANDSHAKE] !globalUnusedTouches.count(thisPointId) " << (!globalUnusedTouches.count(thisPointId)); + if (globalUnusedTouches.count(thisPointId)) { + qDebug() << "[HANDSHAKE] globalUnusedTouches[thisPointId] == button.touchType " << (globalUnusedTouches[thisPointId] == button.touchType); + } + if (!button._found && button._candidatePointIdx == -1 && button.touchBeginIsValid(thisPoint)) { + qDebug() << "[HANDSHAKE] CHECK AGAIN !globalUnusedTouches.count(thisPointId) " << (!globalUnusedTouches.count(thisPointId)); + qDebug() << "[HANDSHAKE] CHECK AGAIN double-check !globalUnusedTouches.count(thisPointId) " << (!globalUnusedTouches.count(thisPointId)); + if (!globalUnusedTouches.count(thisPointId) ) { + button._candidatePointIdx = thisPointIdx; + return true; + } else if (globalUnusedTouches[thisPointId] == button.touchType) { + button._candidatePointIdx = thisPointIdx; + return true; + } + } + } + return false; + +} + +void TouchscreenVirtualPadDevice::TouchscreenButtonsManager::saveUnusedTouches( + std::map &unusedTouchesInEvent, glm::vec2 thisPoint, + int thisPointId) { + for(int i = 0; i < buttons.size(); i++) { + TouchscreenButton &button = buttons[i]; + if (button.touchBeginIsValid(thisPoint)) { + unusedTouchesInEvent[thisPointId] = button.touchType; + return; + } + } + +} + +void TouchscreenVirtualPadDevice::TouchscreenButtonsManager::processBeginOrEnd( + glm::vec2 thisPoint, const QList &tPoints, std::map globalUnusedTouches) { + for(int i = 0; i < buttons.size(); i++) { + TouchscreenButton &button = buttons[i]; + if (!button._found) { + if (button._candidatePointIdx != -1) { + button.currentTouchId = tPoints[button._candidatePointIdx].id(); + globalUnusedTouches.erase(button.currentTouchId); + thisPoint.x = tPoints[button._candidatePointIdx].pos().x(); + thisPoint.y = tPoints[button._candidatePointIdx].pos().y(); + button.touchBegin(thisPoint); + } else { + if (button.hasValidTouch) { + button.touchEnd(); + } + } + } + } + +} + +void TouchscreenVirtualPadDevice::TouchscreenButtonsManager::endTouchForAll() { + for(int i = 0; i < buttons.size(); i++) { + TouchscreenButton &button = buttons[i]; + button.touchEnd(); + } +} + +bool TouchscreenVirtualPadDevice::TouchscreenButtonsManager::touchBeginInvalidForAllButtons(glm::vec2 touchPoint) { + for(int i = 0; i < buttons.size(); i++) { + TouchscreenButton &button = buttons[i]; + if (button.touchBeginIsValid(touchPoint)) { + return false; + } + } + return true; +} diff --git a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h index 9ee3568be3..6ce4a1d412 100644 --- a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h +++ b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h @@ -15,6 +15,7 @@ #include #include "InputPlugin.h" #include +#include #include "VirtualPadManager.h" class QTouchEvent; @@ -87,6 +88,58 @@ protected: RB_BUTTON }; + class TouchscreenButton { + public: + + TouchscreenButton() {}; + + TouchscreenButton(TouchButtonChannel channelIn, TouchType touchTypeIn, float buttonRadiusIn, glm::vec2 buttonPositionIn, + std::shared_ptr inputDeviceIn); + + void touchBegin(glm::vec2 touchPoint); + void touchUpdate(glm::vec2 touchPoint); + void touchEnd(); + bool touchBeginIsValid(glm::vec2 touchPoint); + + bool hasValidTouch { false }; + int currentTouchId; + + // per event tmp values + int _candidatePointIdx { -1 }; + bool _found { false }; + void resetEventValues(); + + glm::vec2 buttonPosition; + float buttonRadius; + TouchType touchType; + TouchButtonChannel channel; + + std::shared_ptr _inputDevice; + + }; + + class TouchscreenButtonsManager { + public: + + TouchscreenButtonsManager(); + + QVector buttons; + + void addButton(TouchscreenButton button); + int buttonsCount() { + return buttons.size(); + } + + void resetEventValues(); + bool processOngoingTouch(glm::vec2 thisPoint, int thisPointId); + bool findStartingTouchPointCandidate(glm::vec2 thisPoint, int thisPointId, int thisPointIdx, std::map &globalUnusedTouches); + void saveUnusedTouches(std::map &unusedTouchesInEvent, glm::vec2 thisPoint, int thisPointId); + void processBeginOrEnd(glm::vec2 thisPoint, const QList& tPoints, std::map globalUnusedTouches); + + void endTouchForAll(); + bool touchBeginInvalidForAllButtons(glm::vec2 touchPoint); + }; + float _lastPinchScale; float _pinchScale; float _screenDPI; @@ -106,9 +159,6 @@ protected: bool _jumpHasValidTouch; int _jumpCurrentTouchId; - bool _rbHasValidTouch; - int _rbCurrentTouchId; - std::map _unusedTouches; int _touchPointCount; @@ -127,6 +177,8 @@ protected: glm::vec2 _rbButtonPosition; float _rbButtonRadius; + TouchscreenButtonsManager _buttonsManager; + void moveTouchBegin(glm::vec2 touchPoint); void moveTouchUpdate(glm::vec2 touchPoint); void moveTouchEnd(); @@ -142,11 +194,6 @@ protected: void jumpTouchEnd(); bool jumpTouchBeginIsValid(glm::vec2 touchPoint); - void rbTouchBegin(glm::vec2 touchPoint); - void rbTouchUpdate(glm::vec2 touchPoint); - void rbTouchEnd(); - bool rbTouchBeginIsValid(glm::vec2 touchPoint); - void setupControlsPositions(VirtualPad::Manager& virtualPadManager, bool force = false); void processInputDeviceForMove(VirtualPad::Manager& virtualPadManager);