From 1ea056a8a9a9fd9567cddb52b24c6c9f45a76508 Mon Sep 17 00:00:00 2001 From: Cristian Luis Duarte Date: Tue, 3 Apr 2018 16:07:40 -0300 Subject: [PATCH] Android - Initial Jump button implementation --- .../controllers/touchscreenvirtualpad.json | 2 + .../Basic2DWindowOpenGLDisplayPlugin.cpp | 42 +++++++- .../Basic2DWindowOpenGLDisplayPlugin.h | 3 + .../TouchscreenVirtualPadDevice.cpp | 95 +++++++++++++++++-- .../TouchscreenVirtualPadDevice.h | 29 +++++- libraries/ui/src/VirtualPadManager.cpp | 17 +++- libraries/ui/src/VirtualPadManager.h | 12 ++- 7 files changed, 181 insertions(+), 19 deletions(-) diff --git a/interface/resources/controllers/touchscreenvirtualpad.json b/interface/resources/controllers/touchscreenvirtualpad.json index 907ff8b403..cdea8681cb 100644 --- a/interface/resources/controllers/touchscreenvirtualpad.json +++ b/interface/resources/controllers/touchscreenvirtualpad.json @@ -5,6 +5,8 @@ { "from": "TouchscreenVirtualPad.LX", "when": "!Application.CameraIndependent", "filters": { "type": "deadZone", "min": 0.05 }, "to": "Actions.TranslateX" }, + { "from": "TouchscreenVirtualPad.JUMP_BUTTON_PRESS", "when": "!Application.CameraIndependent", "to": "Actions.VERTICAL_UP" }, + { "from": "TouchscreenVirtualPad.RX", "when": "!Application.CameraIndependent", "filters": [ {"type": "deadZone", "min": 0.05} , "invert" ], "to": "Actions.Yaw" }, { "from": "TouchscreenVirtualPad.RY", "when": "!Application.CameraIndependent", "filters": [ {"type": "deadZone", "min": 0.05}, "invert" ], "to": "Actions.Pitch" } diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index 97f74fa24e..577330a724 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -25,11 +25,11 @@ static const QString FULLSCREEN = "Fullscreen"; void Basic2DWindowOpenGLDisplayPlugin::customizeContext() { #if defined(Q_OS_ANDROID) + qreal dpi = getFullscreenTarget()->physicalDotsPerInch(); + _virtualPadPixelSize = dpi * VirtualPad::Manager::BASE_DIAMETER_PIXELS / VirtualPad::Manager::DPI; + auto iconPath = PathUtils::resourcesPath() + "images/analog_stick.png"; auto image = QImage(iconPath); - qreal dpi = getFullscreenTarget()->physicalDotsPerInch(); - _virtualPadPixelSize = dpi * VirtualPad::Manager::PIXEL_SIZE / VirtualPad::Manager::DPI; - if (image.format() != QImage::Format_ARGB32) { image = image.convertToFormat(QImage::Format_ARGB32); } @@ -69,6 +69,28 @@ void Basic2DWindowOpenGLDisplayPlugin::customizeContext() { _virtualPadStickBaseTexture->assignStoredMip(0, image.byteCount(), image.constBits()); _virtualPadStickBaseTexture->setAutoGenerateMips(true); } + + _virtualPadJumpBtnPixelSize = dpi * VirtualPad::Manager::JUMP_BTN_FULL_PIXELS / VirtualPad::Manager::DPI; + iconPath = PathUtils::resourcesPath() + "images/analog_stick.png"; + image = QImage(iconPath); + if (image.format() != QImage::Format_ARGB32) { + image = image.convertToFormat(QImage::Format_ARGB32); + } + if ((image.width() > 0) && (image.height() > 0)) { + image = image.scaled(_virtualPadJumpBtnPixelSize, _virtualPadJumpBtnPixelSize, Qt::KeepAspectRatio); + + _virtualPadJumpBtnTexture = gpu::Texture::createStrict( + gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), + image.width(), image.height(), + gpu::Texture::MAX_NUM_MIPS, + gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)); + _virtualPadJumpBtnTexture->setSource("virtualPad jump"); + auto usage = gpu::Texture::Usage::Builder().withColor().withAlpha(); + _virtualPadJumpBtnTexture->setUsage(usage.build()); + _virtualPadJumpBtnTexture->setStoredMipFormat(gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); + _virtualPadJumpBtnTexture->assignStoredMip(0, image.byteCount(), image.constBits()); + _virtualPadJumpBtnTexture->setAutoGenerateMips(true); + } #endif Parent::customizeContext(); } @@ -124,6 +146,20 @@ void Basic2DWindowOpenGLDisplayPlugin::compositeExtra() { batch.setViewportTransform(ivec4(uvec2(0), getRecommendedRenderSize())); batch.draw(gpu::TRIANGLE_STRIP, 4); }); + + // render stick head + auto jumpTransform = DependencyManager::get()->getPoint2DTransform(virtualPadManager.getJumpButtonPosition(), + _virtualPadJumpBtnPixelSize, _virtualPadJumpBtnPixelSize); + render([&](gpu::Batch& batch) { + batch.enableStereo(false); + batch.setProjectionTransform(mat4()); + batch.setPipeline(_cursorPipeline); + batch.setResourceTexture(0, _virtualPadJumpBtnTexture); + batch.resetViewTransform(); + batch.setModelTransform(jumpTransform); + batch.setViewportTransform(ivec4(uvec2(0), getRecommendedRenderSize())); + batch.draw(gpu::TRIANGLE_STRIP, 4); + }); } #endif Parent::compositeExtra(); diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h index 26c48743b7..a061a4c923 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h @@ -46,5 +46,8 @@ private: gpu::TexturePointer _virtualPadStickTexture; gpu::TexturePointer _virtualPadStickBaseTexture; qreal _virtualPadPixelSize; + + gpu::TexturePointer _virtualPadJumpBtnTexture; + qreal _virtualPadJumpBtnPixelSize; #endif }; diff --git a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp index 0a28368e9e..8b922434da 100644 --- a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp @@ -50,12 +50,15 @@ void TouchscreenVirtualPadDevice::init() { _screenDPIProvided = eventScreen->physicalDotsPerInch(); _screenDPI = eventScreen->physicalDotsPerInch(); - _fixedRadius = _screenDPI * 0.5f * VirtualPad::Manager::PIXEL_SIZE / VirtualPad::Manager::DPI; - _fixedRadiusForCalc = _fixedRadius - _screenDPI * VirtualPad::Manager::STICK_RADIUS / VirtualPad::Manager::DPI; + _fixedRadius = _screenDPI * 0.5f * VirtualPad::Manager::BASE_DIAMETER_PIXELS / VirtualPad::Manager::DPI; + _fixedRadiusForCalc = _fixedRadius - _screenDPI * VirtualPad::Manager::STICK_RADIUS_PIXELS / VirtualPad::Manager::DPI; + + _jumpButtonRadius = _screenDPI * VirtualPad::Manager::JUMP_BTN_TRIMMED_RADIUS_PIXELS / VirtualPad::Manager::DPI; } auto& virtualPadManager = VirtualPad::Manager::instance(); setupFixedCenter(virtualPadManager, true); + setupJumpButton(virtualPadManager); if (_fixedPosition) { virtualPadManager.getLeftVirtualPad()->setShown(virtualPadManager.isEnabled() && !virtualPadManager.isHidden()); // Show whenever it's enabled @@ -67,11 +70,10 @@ void TouchscreenVirtualPadDevice::init() { void TouchscreenVirtualPadDevice::setupFixedCenter(VirtualPad::Manager& virtualPadManager, bool force) { if (!_fixedPosition) return; - //auto& virtualPadManager = VirtualPad::Manager::instance(); if (_extraBottomMargin == virtualPadManager.extraBottomMargin() && !force) return; // Our only criteria to decide a center change is the bottom margin _extraBottomMargin = virtualPadManager.extraBottomMargin(); - float margin = _screenDPI * VirtualPad::Manager::BASE_MARGIN / VirtualPad::Manager::DPI; + float margin = _screenDPI * VirtualPad::Manager::BASE_MARGIN_PIXELS / VirtualPad::Manager::DPI; QScreen* eventScreen = qApp->primaryScreen(); // do not call every time _fixedCenterPosition = glm::vec2( _fixedRadius + margin, eventScreen->size().height() - margin - _fixedRadius - _extraBottomMargin); @@ -79,6 +81,13 @@ void TouchscreenVirtualPadDevice::setupFixedCenter(VirtualPad::Manager& virtualP virtualPadManager.getLeftVirtualPad()->setFirstTouch(_moveRefTouchPoint); } +void TouchscreenVirtualPadDevice::setupJumpButton(VirtualPad::Manager& virtualPadManager) { + QScreen* screen = qApp->primaryScreen(); + float topMargin = _screenDPI * VirtualPad::Manager::JUMP_BTN_TOP_MARGIN_PIXELS / VirtualPad::Manager::DPI; + _jumpButtonPosition = glm::vec2( screen->size().width() / 2 + _jumpButtonRadius/2, topMargin + _jumpButtonRadius); + virtualPadManager.setJumpButtonPosition(_jumpButtonPosition); +} + float clip(float n, float lower, float upper) { return std::max(lower, std::min(n, upper)); } @@ -221,6 +230,7 @@ void TouchscreenVirtualPadDevice::touchEndEvent(const QTouchEvent* event) { if (!virtualPadManager.isEnabled() && !virtualPadManager.isHidden()) { moveTouchEnd(); viewTouchEnd(); + jumpTouchEnd(); return; } // touch end here is a big reset -> resets both pads @@ -229,7 +239,9 @@ void TouchscreenVirtualPadDevice::touchEndEvent(const QTouchEvent* event) { debugPoints(event, " END ----------------"); moveTouchEnd(); viewTouchEnd(); + jumpTouchEnd(); _inputDevice->_axisStateMap.clear(); + _inputDevice->_buttonPressedMap.clear(); } void TouchscreenVirtualPadDevice::processUnusedTouches(std::map unusedTouchesInEvent) { @@ -263,9 +275,11 @@ void TouchscreenVirtualPadDevice::touchUpdateEvent(const QTouchEvent* event) { const QList& tPoints = event->touchPoints(); bool moveTouchFound = false; bool viewTouchFound = false; + bool jumpTouchFound = false; int idxMoveStartingPointCandidate = -1; int idxViewStartingPointCandidate = -1; + int idxJumpStartingPointCandidate = -1; glm::vec2 thisPoint; int thisPointId; @@ -290,6 +304,13 @@ void TouchscreenVirtualPadDevice::touchUpdateEvent(const QTouchEvent* event) { continue; } + if (!jumpTouchFound && _jumpHasValidTouch && _jumpCurrentTouchId == thisPointId) { + // valid if it's an ongoing touch + jumpTouchFound = true; + jumpTouchUpdate(thisPoint); + continue; + } + if (!moveTouchFound && idxMoveStartingPointCandidate == -1 && moveTouchBeginIsValid(thisPoint) && (!_unusedTouches.count(thisPointId) || _unusedTouches[thisPointId] == MOVE )) { idxMoveStartingPointCandidate = i; @@ -302,8 +323,16 @@ void TouchscreenVirtualPadDevice::touchUpdateEvent(const QTouchEvent* event) { continue; } + if (!jumpTouchFound && idxJumpStartingPointCandidate == -1 && jumpTouchBeginIsValid(thisPoint) && + (!_unusedTouches.count(thisPointId) || _unusedTouches[thisPointId] == JUMP )) { + idxJumpStartingPointCandidate = i; + continue; + } + if (moveTouchBeginIsValid(thisPoint)) { unusedTouchesInEvent[thisPointId] = MOVE; + } else if (jumpTouchBeginIsValid(thisPoint)) { + unusedTouchesInEvent[thisPointId] = JUMP; } else if (viewTouchBeginIsValid(thisPoint)) { unusedTouchesInEvent[thisPointId] = VIEW; } @@ -330,11 +359,22 @@ void TouchscreenVirtualPadDevice::touchUpdateEvent(const QTouchEvent* event) { viewTouchEnd(); } } + if (!jumpTouchFound) { + if (idxJumpStartingPointCandidate != -1) { + _jumpCurrentTouchId = tPoints[idxJumpStartingPointCandidate].id(); + _unusedTouches.erase(_jumpCurrentTouchId); + jumpTouchBegin(thisPoint); + } else { + if (_jumpHasValidTouch) { + jumpTouchEnd(); + } + } + } } bool TouchscreenVirtualPadDevice::viewTouchBeginIsValid(glm::vec2 touchPoint) { - return !moveTouchBeginIsValid(touchPoint); + return !moveTouchBeginIsValid(touchPoint) && !jumpTouchBeginIsValid(touchPoint); } bool TouchscreenVirtualPadDevice::moveTouchBeginIsValid(glm::vec2 touchPoint) { @@ -347,6 +387,34 @@ bool TouchscreenVirtualPadDevice::moveTouchBeginIsValid(glm::vec2 touchPoint) { } } +bool TouchscreenVirtualPadDevice::jumpTouchBeginIsValid(glm::vec2 touchPoint) { + // position of button and boundaries + return pow(touchPoint.x - _jumpButtonPosition.x, 2.0) + pow(touchPoint.y - _jumpButtonPosition.y, 2.0) < pow(_jumpButtonRadius, 2.0); +} + +void TouchscreenVirtualPadDevice::jumpTouchBegin(glm::vec2 touchPoint) { + auto& virtualPadManager = VirtualPad::Manager::instance(); + if (virtualPadManager.isEnabled() && !virtualPadManager.isHidden()) { + _jumpHasValidTouch = true; + + auto input = _inputDevice->makeInput(TouchButtonChannel::JUMP_BUTTON_PRESS); + _inputDevice->_buttonPressedMap.insert(input.getChannel()); + qDebug() << "[TVPD] TouchscreenVirtualPadDevice::jumpTouchBegin buttonsMapSize " << _inputDevice->_buttonPressedMap.size(); + } +} + +void TouchscreenVirtualPadDevice::jumpTouchUpdate(glm::vec2 touchPoint) {} + +void TouchscreenVirtualPadDevice::jumpTouchEnd() { + if (_jumpHasValidTouch) { + _jumpHasValidTouch = false; + + auto input = _inputDevice->makeInput(TouchButtonChannel::JUMP_BUTTON_PRESS); + _inputDevice->_buttonPressedMap.erase(input.getChannel()); + qDebug() << "[TVPD] TouchscreenVirtualPadDevice::jumpTouchEnd buttonsMapSize " << _inputDevice->_buttonPressedMap.size(); + } +} + void TouchscreenVirtualPadDevice::moveTouchBegin(glm::vec2 touchPoint) { auto& virtualPadManager = VirtualPad::Manager::instance(); if (virtualPadManager.isEnabled() && !virtualPadManager.isHidden()) { @@ -403,13 +471,22 @@ void TouchscreenVirtualPadDevice::touchGestureEvent(const QGestureEvent* event) } } +controller::Input TouchscreenVirtualPadDevice::InputDevice::makeInput(TouchscreenVirtualPadDevice::TouchAxisChannel axis) const { + return controller::Input(_deviceID, axis, controller::ChannelType::AXIS); +} + +controller::Input TouchscreenVirtualPadDevice::InputDevice::makeInput(TouchscreenVirtualPadDevice::TouchButtonChannel button) const { + return controller::Input(_deviceID, button, controller::ChannelType::BUTTON); +} + controller::Input::NamedVector TouchscreenVirtualPadDevice::InputDevice::getAvailableInputs() const { using namespace controller; QVector availableInputs{ - makePair(LX, "LX"), - makePair(LY, "LY"), - makePair(RX, "RX"), - makePair(RY, "RY") + Input::NamedPair(makeInput(TouchAxisChannel::LX), "LX"), + Input::NamedPair(makeInput(TouchAxisChannel::LY), "LY"), + Input::NamedPair(makeInput(TouchAxisChannel::RX), "RX"), + Input::NamedPair(makeInput(TouchAxisChannel::RY), "RY"), + Input::NamedPair(makeInput(TouchButtonChannel::JUMP_BUTTON_PRESS), "JUMP_BUTTON_PRESS") }; return availableInputs; } diff --git a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h index 3540c6d909..010feaf1bb 100644 --- a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h +++ b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h @@ -41,6 +41,17 @@ public: static const char* NAME; + enum TouchAxisChannel { + LX, + LY, + RX, + RY + }; + + enum TouchButtonChannel { + JUMP_BUTTON_PRESS = LY + 1, + }; + protected: class InputDevice : public controller::InputDevice { @@ -54,6 +65,9 @@ protected: virtual void focusOutEvent() override; friend class TouchscreenVirtualPadDevice; + + controller::Input makeInput(TouchAxisChannel axis) const; + controller::Input makeInput(TouchButtonChannel button) const; }; public: @@ -63,7 +77,8 @@ protected: enum TouchType { MOVE = 1, - VIEW + VIEW, + JUMP }; float _lastPinchScale; @@ -82,6 +97,9 @@ protected: glm::vec2 _viewCurrentTouchPoint; int _viewCurrentTouchId; + bool _jumpHasValidTouch; + int _jumpCurrentTouchId; + std::map _unusedTouches; int _touchPointCount; @@ -94,6 +112,9 @@ protected: float _fixedRadiusForCalc; int _extraBottomMargin {0}; + glm::vec2 _jumpButtonPosition; + float _jumpButtonRadius; + float _viewStickRadiusInches {0.1333f}; // agreed default void moveTouchBegin(glm::vec2 touchPoint); @@ -106,7 +127,13 @@ protected: void viewTouchEnd(); bool viewTouchBeginIsValid(glm::vec2 touchPoint); + void jumpTouchBegin(glm::vec2 touchPoint); + void jumpTouchUpdate(glm::vec2 touchPoint); + void jumpTouchEnd(); + bool jumpTouchBeginIsValid(glm::vec2 touchPoint); + void setupFixedCenter(VirtualPad::Manager& virtualPadManager, bool force = false); + void setupJumpButton(VirtualPad::Manager& virtualPadManager); void processInputDeviceForMove(VirtualPad::Manager& virtualPadManager); glm::vec2 clippedPointInCircle(float radius, glm::vec2 origin, glm::vec2 touchPoint); diff --git a/libraries/ui/src/VirtualPadManager.cpp b/libraries/ui/src/VirtualPadManager.cpp index cb3ef20e67..d62a3b076c 100644 --- a/libraries/ui/src/VirtualPadManager.cpp +++ b/libraries/ui/src/VirtualPadManager.cpp @@ -35,9 +35,12 @@ namespace VirtualPad { } const float Manager::DPI = 534.0f; - const float Manager::PIXEL_SIZE = 512.0f; - const float Manager::STICK_RADIUS = 105.0f; - const float Manager::BASE_MARGIN = 59.0f; + const float Manager::BASE_DIAMETER_PIXELS = 512.0f; + const float Manager::BASE_MARGIN_PIXELS = 59.0f; + const float Manager::STICK_RADIUS_PIXELS = 105.0f; + const float Manager::JUMP_BTN_TOP_MARGIN_PIXELS = 59.0f; + const float Manager::JUMP_BTN_TRIMMED_RADIUS_PIXELS = 105.0f; + const float Manager::JUMP_BTN_FULL_PIXELS = 512.0f; Manager::Manager() { @@ -72,6 +75,14 @@ namespace VirtualPad { _extraBottomMargin = margin; } + glm::vec2 Manager::getJumpButtonPosition() { + return _jumpButtonPosition; + } + + void Manager::setJumpButtonPosition(glm::vec2 point) { + _jumpButtonPosition = point; + } + Instance* Manager::getLeftVirtualPad() { return &_leftVPadInstance; } diff --git a/libraries/ui/src/VirtualPadManager.h b/libraries/ui/src/VirtualPadManager.h index 6b68af3acd..b613f6b42e 100644 --- a/libraries/ui/src/VirtualPadManager.h +++ b/libraries/ui/src/VirtualPadManager.h @@ -44,16 +44,22 @@ namespace VirtualPad { void hide(bool hide); int extraBottomMargin(); void setExtraBottomMargin(int margin); + glm::vec2 getJumpButtonPosition(); + void setJumpButtonPosition(glm::vec2 point); static const float DPI; - static const float PIXEL_SIZE; - static const float STICK_RADIUS; - static const float BASE_MARGIN; + static const float BASE_DIAMETER_PIXELS; + static const float BASE_MARGIN_PIXELS; + static const float STICK_RADIUS_PIXELS; + static const float JUMP_BTN_TOP_MARGIN_PIXELS; + static const float JUMP_BTN_TRIMMED_RADIUS_PIXELS; + static const float JUMP_BTN_FULL_PIXELS; private: Instance _leftVPadInstance; bool _enabled; bool _hidden; + glm::vec2 _jumpButtonPosition; int _extraBottomMargin {0}; }; }