From 6ad1008a566f179e7752af7456c5d3a4a3e55efa Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Wed, 15 Jun 2016 13:42:48 -0700 Subject: [PATCH 1/3] Allow explicit overlay alpha from scripts --- .../scripting/DesktopScriptingInterface.cpp | 6 +++++ .../src/scripting/DesktopScriptingInterface.h | 2 ++ .../src/display-plugins/CompositorHelper.h | 6 +++++ .../display-plugins/OpenGLDisplayPlugin.cpp | 27 +++++++++++++++++++ .../src/display-plugins/OpenGLDisplayPlugin.h | 8 +++++- .../display-plugins/hmd/HmdDisplayPlugin.cpp | 9 ++++++- .../oculus/src/OculusBaseDisplayPlugin.cpp | 2 +- .../src/OculusLegacyDisplayPlugin.cpp | 3 ++- plugins/openvr/src/OpenVrDisplayPlugin.cpp | 2 +- 9 files changed, 60 insertions(+), 5 deletions(-) diff --git a/interface/src/scripting/DesktopScriptingInterface.cpp b/interface/src/scripting/DesktopScriptingInterface.cpp index 843a40348e..f7bc8afe36 100644 --- a/interface/src/scripting/DesktopScriptingInterface.cpp +++ b/interface/src/scripting/DesktopScriptingInterface.cpp @@ -16,6 +16,7 @@ #include "Application.h" #include "MainWindow.h" +#include int DesktopScriptingInterface::getWidth() { QSize size = qApp->getWindow()->windowHandle()->screen()->virtualSize(); @@ -25,3 +26,8 @@ int DesktopScriptingInterface::getHeight() { QSize size = qApp->getWindow()->windowHandle()->screen()->virtualSize(); return size.height(); } + +void DesktopScriptingInterface::setOverlayAlpha(float alpha) { + qApp->getApplicationCompositor().setAlpha(alpha); +} + diff --git a/interface/src/scripting/DesktopScriptingInterface.h b/interface/src/scripting/DesktopScriptingInterface.h index be4eaadbfb..8da502cb11 100644 --- a/interface/src/scripting/DesktopScriptingInterface.h +++ b/interface/src/scripting/DesktopScriptingInterface.h @@ -22,6 +22,8 @@ class DesktopScriptingInterface : public QObject, public Dependency { Q_PROPERTY(int height READ getHeight) // Physical height of screen(s) including task bars and system menus public: + Q_INVOKABLE void setOverlayAlpha(float alpha); + int getWidth(); int getHeight(); }; diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.h b/libraries/display-plugins/src/display-plugins/CompositorHelper.h index 868beec53f..2a3dd0c852 100644 --- a/libraries/display-plugins/src/display-plugins/CompositorHelper.h +++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.h @@ -38,6 +38,7 @@ const float MAGNIFY_MULT = 2.0f; class CompositorHelper : public QObject, public Dependency { Q_OBJECT + Q_PROPERTY(float alpha READ getAlpha WRITE setAlpha NOTIFY alphaChanged) Q_PROPERTY(bool reticleOverDesktop READ getReticleOverDesktop WRITE setReticleOverDesktop) public: static const uvec2 VIRTUAL_SCREEN_SIZE; @@ -74,6 +75,9 @@ public: void setModelTransform(const Transform& transform) { _modelTransform = transform; } const Transform& getModelTransform() const { return _modelTransform; } + float getAlpha() const { return _alpha; } + void setAlpha(float alpha) { if (alpha != _alpha) { emit alphaChanged(); _alpha = alpha; } } + bool getReticleVisible() const { return _reticleVisible; } void setReticleVisible(bool visible) { _reticleVisible = visible; } @@ -109,6 +113,7 @@ public: signals: void allowMouseCaptureChanged(); + void alphaChanged(); protected slots: void sendFakeMouseEvent(); @@ -134,6 +139,7 @@ private: float _textureFov { VIRTUAL_UI_TARGET_FOV.y }; float _textureAspectRatio { VIRTUAL_UI_ASPECT_RATIO }; + float _alpha { 1.0f }; float _hmdUIRadius { 1.0f }; int _previousBorderWidth { -1 }; diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 23c836b3de..b49b41d8b2 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -273,11 +273,23 @@ bool OpenGLDisplayPlugin::activate() { _container->makeRenderingContextCurrent(); #endif + auto compositorHelper = DependencyManager::get(); + connect(compositorHelper.data(), &CompositorHelper::alphaChanged, [this] { + auto compositorHelper = DependencyManager::get(); + auto animation = new QPropertyAnimation(this, "overlayAlpha"); + animation->setDuration(200); + animation->setEndValue(compositorHelper->getAlpha()); + animation->start(); + }); + return DisplayPlugin::activate(); } void OpenGLDisplayPlugin::deactivate() { + auto compositorHelper = DependencyManager::get(); + disconnect(compositorHelper.data()); + #if THREADED_PRESENT auto presentThread = DependencyManager::get(); // Does not return until the GL transition has completeed @@ -445,6 +457,8 @@ void OpenGLDisplayPlugin::compositeOverlay() { auto compositorHelper = DependencyManager::get(); useProgram(_program); + // set the alpha + Uniform(*_program, _alphaUniform).Set(_compositeOverlayAlpha); // check the alpha // Overlay draw if (isStereo()) { @@ -458,6 +472,8 @@ void OpenGLDisplayPlugin::compositeOverlay() { Uniform(*_program, _mvpUniform).Set(mat4()); drawUnitQuad(); } + // restore the alpha + Uniform(*_program, _alphaUniform).Set(1.0); } void OpenGLDisplayPlugin::compositePointer() { @@ -465,6 +481,8 @@ void OpenGLDisplayPlugin::compositePointer() { auto compositorHelper = DependencyManager::get(); useProgram(_program); + // set the alpha + Uniform(*_program, _alphaUniform).Set(_compositeOverlayAlpha); Uniform(*_program, _mvpUniform).Set(compositorHelper->getReticleTransform(glm::mat4())); if (isStereo()) { for_each_eye([&](Eye eye) { @@ -475,6 +493,8 @@ void OpenGLDisplayPlugin::compositePointer() { drawUnitQuad(); } Uniform(*_program, _mvpUniform).Set(mat4()); + // restore the alpha + Uniform(*_program, _alphaUniform).Set(1.0); } void OpenGLDisplayPlugin::compositeScene() { @@ -682,3 +702,10 @@ void OpenGLDisplayPlugin::assertIsRenderThread() const { void OpenGLDisplayPlugin::assertIsPresentThread() const { Q_ASSERT(QThread::currentThread() == _presentThread); } + +bool OpenGLDisplayPlugin::beginFrameRender(uint32_t frameIndex) { + withRenderThreadLock([&] { + _compositeOverlayAlpha = _overlayAlpha; + }); + return Parent::beginFrameRender(frameIndex); +} diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index 69653b8c76..d8d4d8ff8c 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -24,6 +24,9 @@ #define THREADED_PRESENT 1 class OpenGLDisplayPlugin : public DisplayPlugin { + Q_OBJECT + Q_PROPERTY(float overlayAlpha MEMBER _overlayAlpha) + using Parent = DisplayPlugin; protected: using Mutex = std::mutex; using Lock = std::unique_lock; @@ -60,6 +63,7 @@ public: float droppedFrameRate() const override; + bool beginFrameRender(uint32_t frameIndex) override; protected: #if THREADED_PRESENT friend class PresentThread; @@ -115,7 +119,8 @@ protected: RateCounter<> _presentRate; QMap _sceneTextureToFrameIndexMap; uint32_t _currentPresentFrameIndex { 0 }; - + float _compositeOverlayAlpha{ 1.0f }; + gpu::TexturePointer _currentSceneTexture; gpu::TexturePointer _currentOverlayTexture; @@ -157,6 +162,7 @@ private: // be serialized through this mutex mutable Mutex _presentMutex; ProgramPtr _activeProgram; + float _overlayAlpha{ 1.0f }; }; diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp index 6801d94f2f..efdb68226b 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp @@ -287,6 +287,8 @@ void HmdDisplayPlugin::compositeOverlay() { glm::mat4 modelMat = compositorHelper->getModelTransform().getMatrix(); useProgram(_program); + // set the alpha + Uniform(*_program, _alphaUniform).Set(_compositeOverlayAlpha); _sphereSection->Use(); for_each_eye([&](Eye eye) { eyeViewport(eye); @@ -295,6 +297,8 @@ void HmdDisplayPlugin::compositeOverlay() { Uniform(*_program, _mvpUniform).Set(mvp); _sphereSection->Draw(); }); + // restore the alpha + Uniform(*_program, _alphaUniform).Set(1.0); } void HmdDisplayPlugin::compositePointer() { @@ -302,8 +306,9 @@ void HmdDisplayPlugin::compositePointer() { auto compositorHelper = DependencyManager::get(); - // check the alpha useProgram(_program); + // set the alpha + Uniform(*_program, _alphaUniform).Set(_compositeOverlayAlpha); // Mouse pointer _plane->Use(); @@ -317,6 +322,8 @@ void HmdDisplayPlugin::compositePointer() { Uniform(*_program, _mvpUniform).Set(mvp); _plane->Draw(); }); + // restore the alpha + Uniform(*_program, _alphaUniform).Set(1.0); } diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp index e188bea52e..e26a48b89c 100644 --- a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp @@ -45,7 +45,7 @@ bool OculusBaseDisplayPlugin::beginFrameRender(uint32_t frameIndex) { _handPoses = handPoses; _frameInfos[frameIndex] = _currentRenderFrameInfo; }); - return true; + return Parent::beginFrameRender(frameIndex); } bool OculusBaseDisplayPlugin::isSupported() const { diff --git a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.cpp b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.cpp index 8d2bc24177..699891deaa 100644 --- a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.cpp +++ b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.cpp @@ -41,6 +41,7 @@ void OculusLegacyDisplayPlugin::resetSensors() { } bool OculusLegacyDisplayPlugin::beginFrameRender(uint32_t frameIndex) { + _currentRenderFrameInfo = FrameInfo(); _currentRenderFrameInfo.predictedDisplayTime = _currentRenderFrameInfo.sensorSampleTime = ovr_GetTimeInSeconds(); _trackingState = ovrHmd_GetTrackingState(_hmd, _currentRenderFrameInfo.predictedDisplayTime); @@ -48,7 +49,7 @@ bool OculusLegacyDisplayPlugin::beginFrameRender(uint32_t frameIndex) { withRenderThreadLock([&]{ _frameInfos[frameIndex] = _currentRenderFrameInfo; }); - return true; + return Parent::beginFrameRender(frameIndex); } bool OculusLegacyDisplayPlugin::isSupported() const { diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index acbf386980..a92c930cbf 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -204,7 +204,7 @@ bool OpenVrDisplayPlugin::beginFrameRender(uint32_t frameIndex) { _handPoses = handPoses; _frameInfos[frameIndex] = _currentRenderFrameInfo; }); - return true; + return Parent::beginFrameRender(frameIndex); } void OpenVrDisplayPlugin::hmdPresent() { From 33e9caa63687f0682d3eff619e963b8952a23b2a Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Wed, 15 Jun 2016 17:20:18 -0700 Subject: [PATCH 2/3] Simplify overlay conductor, menu interation --- .../resources/qml/hifi/ToggleHudButton.qml | 4 +- interface/src/Application.cpp | 13 +- interface/src/ui/OverlayConductor.cpp | 112 +++++------------- interface/src/ui/OverlayConductor.h | 23 +--- 4 files changed, 42 insertions(+), 110 deletions(-) diff --git a/interface/resources/qml/hifi/ToggleHudButton.qml b/interface/resources/qml/hifi/ToggleHudButton.qml index 6454f42305..63c056b352 100644 --- a/interface/resources/qml/hifi/ToggleHudButton.qml +++ b/interface/resources/qml/hifi/ToggleHudButton.qml @@ -16,6 +16,8 @@ Window { height: 50 clip: true visible: true + // Disable this window from being able to call 'desktop.raise() and desktop.showDesktop' + activator: Item {} Item { width: 50 @@ -28,7 +30,7 @@ Window { MouseArea { readonly property string overlayMenuItem: "Overlays" anchors.fill: parent - onClicked: MenuInterface.setIsOptionChecked(overlayMenuItem, !MenuInterface.isOptionChecked(overlayMenuItem)) + onClicked: MenuInterface.setIsOptionChecked(overlayMenuItem, !MenuInterface.isOptionChecked(overlayMenuItem)); } } } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ec86f5f1e0..29238cf153 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2716,7 +2716,6 @@ void Application::idle(float nsecsElapsed) { if (firstIdle) { firstIdle = false; connect(offscreenUi.data(), &OffscreenUi::showDesktop, this, &Application::showDesktop); - _overlayConductor.setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Overlays)); } PROFILE_RANGE(__FUNCTION__); @@ -3217,13 +3216,13 @@ void Application::updateThreads(float deltaTime) { } void Application::toggleOverlays() { - auto newOverlaysVisible = !_overlayConductor.getEnabled(); - Menu::getInstance()->setIsOptionChecked(MenuOption::Overlays, newOverlaysVisible); - _overlayConductor.setEnabled(newOverlaysVisible); + auto menu = Menu::getInstance(); + menu->setIsOptionChecked(MenuOption::Overlays, menu->isOptionChecked(MenuOption::Overlays)); } void Application::setOverlaysVisible(bool visible) { - _overlayConductor.setEnabled(visible); + auto menu = Menu::getInstance(); + menu->setIsOptionChecked(MenuOption::Overlays, true); } void Application::cycleCamera() { @@ -5306,9 +5305,7 @@ void Application::readArgumentsFromLocalSocket() const { } void Application::showDesktop() { - if (!_overlayConductor.getEnabled()) { - _overlayConductor.setEnabled(true); - } + Menu::getInstance()->setIsOptionChecked(MenuOption::Overlays, true); } CompositorHelper& Application::getApplicationCompositor() const { diff --git a/interface/src/ui/OverlayConductor.cpp b/interface/src/ui/OverlayConductor.cpp index a897d85472..a455147bb8 100644 --- a/interface/src/ui/OverlayConductor.cpp +++ b/interface/src/ui/OverlayConductor.cpp @@ -99,104 +99,50 @@ void OverlayConductor::centerUI() { qApp->getApplicationCompositor().setModelTransform(Transform(camMat)); } -bool OverlayConductor::userWishesToHide() const { - // user pressed toggle button. - return Menu::getInstance()->isOptionChecked(MenuOption::Overlays) != _prevOverlayMenuChecked && Menu::getInstance()->isOptionChecked(MenuOption::Overlays); -} - -bool OverlayConductor::userWishesToShow() const { - // user pressed toggle button. - return Menu::getInstance()->isOptionChecked(MenuOption::Overlays) != _prevOverlayMenuChecked && !Menu::getInstance()->isOptionChecked(MenuOption::Overlays); -} - -void OverlayConductor::setState(State state) { -#ifdef WANT_DEBUG - static QString stateToString[NumStates] = { "Enabled", "DisabledByDrive", "DisabledByHead", "DisabledByToggle" }; - qDebug() << "OverlayConductor " << stateToString[state] << "<--" << stateToString[_state]; -#endif - _state = state; -} - -OverlayConductor::State OverlayConductor::getState() const { - return _state; -} - void OverlayConductor::update(float dt) { + auto offscreenUi = DependencyManager::get(); + bool currentVisible = !offscreenUi->getDesktop()->property("pinned").toBool(); MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); - - // centerUI when hmd mode is first enabled - if (qApp->isHMDMode() && !_hmdMode) { + // centerUI when hmd mode is first enabled and mounted + if (qApp->isHMDMode() && qApp->getActiveDisplayPlugin()->isDisplayVisible() && !_hmdMode) { + _hmdMode = true; centerUI(); + } else { + _hmdMode = false; } - _hmdMode = qApp->isHMDMode(); bool prevDriving = _currentDriving; bool isDriving = updateAvatarHasDriveInput(); bool drivingChanged = prevDriving != isDriving; - bool isAtRest = updateAvatarIsAtRest(); - switch (getState()) { - case Enabled: - if (myAvatar->getClearOverlayWhenDriving() && qApp->isHMDMode() && headOutsideOverlay()) { - setState(DisabledByHead); - setEnabled(false); - } - if (userWishesToHide()) { - setState(DisabledByToggle); - setEnabled(false); - } - if (myAvatar->getClearOverlayWhenDriving() && drivingChanged && isDriving) { - setState(DisabledByDrive); - setEnabled(false); - } - break; - case DisabledByDrive: - if (!isDriving || userWishesToShow()) { - setState(Enabled); - setEnabled(true); - } - break; - case DisabledByHead: - if (isAtRest || userWishesToShow()) { - setState(Enabled); - setEnabled(true); - } - break; - case DisabledByToggle: - if (userWishesToShow()) { - setState(Enabled); - setEnabled(true); - } - break; - default: - break; + if (_flags & SuppressedByDrive) { + if (!isDriving) { + _flags &= ~SuppressedByDrive; + } + } else { + if (myAvatar->getClearOverlayWhenDriving() && drivingChanged && isDriving) { + _flags |= SuppressedByDrive; + } } - _prevOverlayMenuChecked = Menu::getInstance()->isOptionChecked(MenuOption::Overlays); -} - -void OverlayConductor::setEnabled(bool enabled) { - if (enabled == _enabled) { - return; + if (_flags & SuppressedByHead) { + if (isAtRest) { + _flags &= ~SuppressedByHead; + } + } else { + if (_hmdMode && headOutsideOverlay()) { + _flags |= SuppressedByHead; + } } - _enabled = enabled; // set the new value - auto offscreenUi = DependencyManager::get(); - offscreenUi->setPinned(!_enabled); - // ensure that the the state of the menu item reflects the state of the overlay. - Menu::getInstance()->setIsOptionChecked(MenuOption::Overlays, _enabled); - _prevOverlayMenuChecked = _enabled; - - // if the new state is visible/enabled... - if (_enabled && qApp->isHMDMode()) { - centerUI(); + bool targetVisible = Menu::getInstance()->isOptionChecked(MenuOption::Overlays) && (0 == (_flags & SuppressMask)); + if (targetVisible != currentVisible) { + offscreenUi->setPinned(!targetVisible); + if (targetVisible && _hmdMode) { + centerUI(); + } } } - -bool OverlayConductor::getEnabled() const { - return _enabled; -} - diff --git a/interface/src/ui/OverlayConductor.h b/interface/src/ui/OverlayConductor.h index 375b2652f6..1bdfe2ed79 100644 --- a/interface/src/ui/OverlayConductor.h +++ b/interface/src/ui/OverlayConductor.h @@ -17,33 +17,20 @@ public: ~OverlayConductor(); void update(float dt); - void setEnabled(bool enable); - bool getEnabled() const; - void centerUI(); private: bool headOutsideOverlay() const; bool updateAvatarHasDriveInput(); bool updateAvatarIsAtRest(); - bool userWishesToHide() const; - bool userWishesToShow() const; - enum State { - Enabled = 0, - DisabledByDrive, - DisabledByHead, - DisabledByToggle, - NumStates + enum SupressionFlags { + SuppressedByDrive = 0x01, + SuppressedByHead = 0x02, + SuppressMask = 0x03, }; - void setState(State state); - State getState() const; - - State _state { DisabledByDrive }; - - bool _prevOverlayMenuChecked { true }; - bool _enabled { false }; + uint8_t _flags { SuppressedByDrive }; bool _hmdMode { false }; // used by updateAvatarHasDriveInput From 067539ff6d3bb1de82ba5ebd79542e79228ac767 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Wed, 15 Jun 2016 17:44:58 -0700 Subject: [PATCH 3/3] Fix overlay stuck to face --- interface/src/ui/OverlayConductor.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/OverlayConductor.cpp b/interface/src/ui/OverlayConductor.cpp index a455147bb8..74e27122e4 100644 --- a/interface/src/ui/OverlayConductor.cpp +++ b/interface/src/ui/OverlayConductor.cpp @@ -105,9 +105,11 @@ void OverlayConductor::update(float dt) { MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); // centerUI when hmd mode is first enabled and mounted - if (qApp->isHMDMode() && qApp->getActiveDisplayPlugin()->isDisplayVisible() && !_hmdMode) { - _hmdMode = true; - centerUI(); + if (qApp->isHMDMode() && qApp->getActiveDisplayPlugin()->isDisplayVisible()) { + if (!_hmdMode) { + _hmdMode = true; + centerUI(); + } } else { _hmdMode = false; }