From 0d873c7732b3f834b972565b1310cf656d802f8f Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Mon, 15 Feb 2016 16:11:25 -0800 Subject: [PATCH 01/72] consolidate all calls to QCursor::pos() and QCursor.setPosition() to use common ControllerScriptingInterface --- interface/src/Application.cpp | 44 +++++-------------- .../scripting/WindowScriptingInterface.cpp | 12 ----- .../src/scripting/WindowScriptingInterface.h | 3 -- libraries/ui/src/CursorManager.cpp | 14 ------ libraries/ui/src/CursorManager.h | 5 --- 5 files changed, 11 insertions(+), 67 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index cf4c35209d..461e5e56ba 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -806,39 +806,14 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : } else if (action == controller::toInt(controller::Action::CYCLE_CAMERA)) { cycleCamera(); } else if (action == controller::toInt(controller::Action::CONTEXT_MENU)) { - offscreenUi->toggleMenu(_glWidget->mapFromGlobal(QCursor::pos())); + auto reticlePosition = _controllerScriptingInterface->getReticlePosition(); + offscreenUi->toggleMenu(_glWidget->mapFromGlobal(QPoint(reticlePosition.x, reticlePosition.y))); } else if (action == controller::toInt(controller::Action::RETICLE_X)) { - auto oldPos = QCursor::pos(); - auto newPos = oldPos; - newPos.setX(oldPos.x() + state); - QCursor::setPos(newPos); - - - // NOTE: This is some debugging code we will leave in while debugging various reticle movement strategies, - // remove it after we're done - const float REASONABLE_CHANGE = 50.0f; - glm::vec2 oldPosG = { oldPos.x(), oldPos.y() }; - glm::vec2 newPosG = { newPos.x(), newPos.y() }; - auto distance = glm::distance(oldPosG, newPosG); - if (distance > REASONABLE_CHANGE) { - qDebug() << "Action::RETICLE_X... UNREASONABLE CHANGE! distance:" << distance << " oldPos:" << oldPosG << " newPos:" << newPosG; - } - + auto oldPos = _controllerScriptingInterface->getReticlePosition(); + _controllerScriptingInterface->setReticlePosition({ oldPos.x + state, oldPos.y }); } else if (action == controller::toInt(controller::Action::RETICLE_Y)) { - auto oldPos = QCursor::pos(); - auto newPos = oldPos; - newPos.setY(oldPos.y() + state); - QCursor::setPos(newPos); - - // NOTE: This is some debugging code we will leave in while debugging various reticle movement strategies, - // remove it after we're done - const float REASONABLE_CHANGE = 50.0f; - glm::vec2 oldPosG = { oldPos.x(), oldPos.y() }; - glm::vec2 newPosG = { newPos.x(), newPos.y() }; - auto distance = glm::distance(oldPosG, newPosG); - if (distance > REASONABLE_CHANGE) { - qDebug() << "Action::RETICLE_Y... UNREASONABLE CHANGE! distance:" << distance << " oldPos:" << oldPosG << " newPos:" << newPosG; - } + auto oldPos = _controllerScriptingInterface->getReticlePosition(); + _controllerScriptingInterface->setReticlePosition({ oldPos.x, oldPos.y + state }); } } }); @@ -2110,7 +2085,8 @@ void Application::keyPressEvent(QKeyEvent* event) { void Application::keyReleaseEvent(QKeyEvent* event) { if (event->key() == Qt::Key_Alt && _altPressed && hasFocus()) { auto offscreenUi = DependencyManager::get(); - offscreenUi->toggleMenu(_glWidget->mapFromGlobal(QCursor::pos())); + auto reticlePosition = _controllerScriptingInterface->getReticlePosition(); + offscreenUi->toggleMenu(_glWidget->mapFromGlobal(QPoint(reticlePosition.x, reticlePosition.y))); } _keysPressed.remove(event->key()); @@ -4727,8 +4703,10 @@ bool Application::isThrottleRendering() const { return getActiveDisplayPlugin()->isThrottled(); } +// FIXME -- consolidate users of getTrueMouse() controllerScriptingInterface->getReticlePosition() ivec2 Application::getTrueMouse() const { - return toGlm(_glWidget->mapFromGlobal(QCursor::pos())); + auto reticlePosition = _controllerScriptingInterface->getReticlePosition(); + return toGlm(_glWidget->mapFromGlobal(QPoint(reticlePosition.x, reticlePosition.y))); } bool Application::hasFocus() const { diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index 3e8d0d0360..b8c82498a1 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -64,18 +64,6 @@ void WindowScriptingInterface::raiseMainWindow() { }); } -void WindowScriptingInterface::setCursorPosition(int x, int y) { - QCursor::setPos(x, y); -} - -QScriptValue WindowScriptingInterface::getCursorPositionX() { - return QCursor::pos().x(); -} - -QScriptValue WindowScriptingInterface::getCursorPositionY() { - return QCursor::pos().y(); -} - /// Display an alert box /// \param const QString& message message to display /// \return QScriptValue::UndefinedValue diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index d00e63b49e..609915bdc7 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -32,9 +32,6 @@ public: int getY(); public slots: - QScriptValue getCursorPositionX(); - QScriptValue getCursorPositionY(); - void setCursorPosition(int x, int y); QScriptValue hasFocus(); void setFocus(); void raiseMainWindow(); diff --git a/libraries/ui/src/CursorManager.cpp b/libraries/ui/src/CursorManager.cpp index 50873a31a3..cfa96b7992 100644 --- a/libraries/ui/src/CursorManager.cpp +++ b/libraries/ui/src/CursorManager.cpp @@ -29,20 +29,6 @@ namespace Cursor { Source getType() const { return Source::MOUSE; } - - ivec2 getScreenPosition() const { - return toGlm(QCursor::pos()); - } - - ivec2 getWindowPosition(QWidget* widget) const { - return toGlm(widget->mapFromGlobal(QCursor::pos())); - } - - vec2 getRelativePosition(QWidget* widget) const { - vec2 pos = getWindowPosition(widget); - pos /= vec2(toGlm(widget->size())); - return pos; - } }; static QMap ICONS; diff --git a/libraries/ui/src/CursorManager.h b/libraries/ui/src/CursorManager.h index c5810caf58..7ecab76be8 100644 --- a/libraries/ui/src/CursorManager.h +++ b/libraries/ui/src/CursorManager.h @@ -14,8 +14,6 @@ namespace Cursor { enum class Source { MOUSE, - LEFT_HAND, - RIGHT_HAND, UNKNOWN, }; @@ -33,9 +31,6 @@ namespace Cursor { class Instance { public: virtual Source getType() const = 0; - virtual ivec2 getWindowPosition(QWidget* widget) const = 0; - virtual vec2 getRelativePosition(QWidget* widget) const = 0; - virtual ivec2 getScreenPosition() const = 0; virtual void setIcon(uint16_t icon); virtual uint16_t getIcon() const; private: From 4255b1f9aa71bcac16af27ec162e0d4bdea22ce9 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Tue, 16 Feb 2016 11:22:01 -0800 Subject: [PATCH 02/72] Change output buffer size on correct thread, and turn on automatic resizing on all platforms instead of just mac. --- libraries/audio-client/src/AudioClient.cpp | 6 ++++-- libraries/audio-client/src/AudioClient.h | 7 ++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 60c9287912..73343b510e 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -976,7 +976,8 @@ void AudioClient::outputNotify() { setOutputBufferSize(newOutputBufferSizeFrames); newOutputBufferSizeFrames = _outputBufferSizeFrames.get(); if (newOutputBufferSizeFrames > oldOutputBufferSizeFrames) { - qCDebug(audioclient) << "Starve detection threshold met, increasing buffer size to " << newOutputBufferSizeFrames; + qCDebug(audioclient) << "Starve detection threshold met, increasing buffer size to " << newOutputBufferSizeFrames << + "on period size" << _audioOutput->periodSize() << "bytes."; } } } @@ -1041,6 +1042,7 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDevice _audioOutput->setBufferSize(_outputBufferSizeFrames.get() * _outputFrameSize * sizeof(int16_t)); connect(_audioOutput, &QAudioOutput::notify, this, &AudioClient::outputNotify); + connect(this, &AudioClient::changeDevice, this, [=](const QAudioDeviceInfo& outputDeviceInfo) { switchOutputToAudioDevice(outputDeviceInfo); }); qCDebug(audioclient) << "Output Buffer capacity in frames: " << _audioOutput->bufferSize() / sizeof(int16_t) / (float)_outputFrameSize; @@ -1070,7 +1072,7 @@ void AudioClient::setOutputBufferSize(int numFrames) { // The buffer size can't be adjusted after QAudioOutput::start() has been called, so // recreate the device by switching to the default. QAudioDeviceInfo outputDeviceInfo = defaultAudioDeviceForMode(QAudio::AudioOutput); - switchOutputToAudioDevice(outputDeviceInfo); + emit changeDevice(outputDeviceInfo); // On correct thread, please, as setOutputBufferSize can be called from main thread. } } } diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index 6b2f39c47c..47eef0762e 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -57,11 +57,7 @@ static const int NUM_AUDIO_CHANNELS = 2; static const int DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 3; static const int MIN_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 1; static const int MAX_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 20; -#if defined(Q_OS_ANDROID) || defined(Q_OS_WIN) - static const int DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_ENABLED = false; -#else - static const int DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_ENABLED = true; -#endif +static const int DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_ENABLED = true; static const int DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_THRESHOLD = 3; static const quint64 DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_PERIOD = 10 * 1000; // 10 Seconds @@ -184,6 +180,7 @@ signals: void outputBytesToNetwork(int numBytes); void inputBytesFromNetwork(int numBytes); + void changeDevice(const QAudioDeviceInfo& outputDeviceInfo); void deviceChanged(); void receivedFirstPacket(); From d328b82c3cb99d7869e3fe97efde810690b800d8 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Tue, 16 Feb 2016 12:09:44 -0800 Subject: [PATCH 03/72] Default output buffer size is 1 frame, and automatic updates don't persist changes (just in-memory). --- libraries/audio-client/src/AudioClient.cpp | 19 +++++++++++-------- libraries/audio-client/src/AudioClient.h | 5 +++-- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 73343b510e..f7dc0c65bb 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -81,6 +81,7 @@ AudioClient::AudioClient() : _outputStarveDetectionStartTimeMsec(0), _outputStarveDetectionCount(0), _outputBufferSizeFrames("audioOutputBufferSize", DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES), + _sessionOutputBufferSizeFrames(_outputBufferSizeFrames.get()), _outputStarveDetectionEnabled("audioOutputStarveDetectionEnabled", DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_ENABLED), _outputStarveDetectionPeriodMsec("audioOutputStarveDetectionPeriod", @@ -971,10 +972,8 @@ void AudioClient::outputNotify() { _outputStarveDetectionStartTimeMsec = now; _outputStarveDetectionCount = 0; - int oldOutputBufferSizeFrames = _outputBufferSizeFrames.get(); - int newOutputBufferSizeFrames = oldOutputBufferSizeFrames + 1; - setOutputBufferSize(newOutputBufferSizeFrames); - newOutputBufferSizeFrames = _outputBufferSizeFrames.get(); + int oldOutputBufferSizeFrames = _sessionOutputBufferSizeFrames; + int newOutputBufferSizeFrames = setOutputBufferSize(oldOutputBufferSizeFrames + 1, false); if (newOutputBufferSizeFrames > oldOutputBufferSizeFrames) { qCDebug(audioclient) << "Starve detection threshold met, increasing buffer size to " << newOutputBufferSizeFrames << "on period size" << _audioOutput->periodSize() << "bytes."; @@ -1039,7 +1038,7 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDevice // setup our general output device for audio-mixer audio _audioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this); - _audioOutput->setBufferSize(_outputBufferSizeFrames.get() * _outputFrameSize * sizeof(int16_t)); + _audioOutput->setBufferSize(_sessionOutputBufferSizeFrames *_outputFrameSize * sizeof(int16_t)); connect(_audioOutput, &QAudioOutput::notify, this, &AudioClient::outputNotify); connect(this, &AudioClient::changeDevice, this, [=](const QAudioDeviceInfo& outputDeviceInfo) { switchOutputToAudioDevice(outputDeviceInfo); }); @@ -1062,11 +1061,14 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDevice return supportedFormat; } -void AudioClient::setOutputBufferSize(int numFrames) { +int AudioClient::setOutputBufferSize(int numFrames, bool persist) { numFrames = std::min(std::max(numFrames, MIN_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES), MAX_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES); - if (numFrames != _outputBufferSizeFrames.get()) { + if (numFrames != _sessionOutputBufferSizeFrames) { qCDebug(audioclient) << "Audio output buffer size (frames): " << numFrames; - _outputBufferSizeFrames.set(numFrames); + _sessionOutputBufferSizeFrames = numFrames; + if (persist) { + _outputBufferSizeFrames.set(numFrames); + } if (_audioOutput) { // The buffer size can't be adjusted after QAudioOutput::start() has been called, so @@ -1075,6 +1077,7 @@ void AudioClient::setOutputBufferSize(int numFrames) { emit changeDevice(outputDeviceInfo); // On correct thread, please, as setOutputBufferSize can be called from main thread. } } + return numFrames; } // The following constant is operating system dependent due to differences in diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index 47eef0762e..3a93c1e1b3 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -54,7 +54,7 @@ static const int NUM_AUDIO_CHANNELS = 2; -static const int DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 3; +static const int DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 1; static const int MIN_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 1; static const int MAX_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 20; static const int DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_ENABLED = true; @@ -152,7 +152,7 @@ public slots: void processReceivedSamples(const QByteArray& inputBuffer, QByteArray& outputBuffer); void sendMuteEnvironmentPacket(); - void setOutputBufferSize(int numFrames); + int setOutputBufferSize(int numFrames, bool persist = true); virtual bool outputLocalInjector(bool isStereo, AudioInjector* injector); @@ -227,6 +227,7 @@ private: int _outputStarveDetectionCount; Setting::Handle _outputBufferSizeFrames; + int _sessionOutputBufferSizeFrames; Setting::Handle _outputStarveDetectionEnabled; Setting::Handle _outputStarveDetectionPeriodMsec; // Maximum number of starves per _outputStarveDetectionPeriod before increasing buffer size From a25581c656d02419f303a04cff38f7d1b2fd5cab Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Tue, 16 Feb 2016 12:11:58 -0800 Subject: [PATCH 04/72] clean up reticle scripting to be exposed through Reticle object (implemented int ApplicationCompositor) --- examples/controllers/handControllerGrab.js | 6 +- examples/controllers/philipsVersion.js | 6 +- .../reticleHandAngularVelocityTest.js | 6 +- .../controllers/reticleHandRotationTest.js | 4 +- interface/src/Application.cpp | 26 ++++---- interface/src/Application.h | 8 +-- interface/src/ui/ApplicationCompositor.cpp | 10 +-- interface/src/ui/ApplicationCompositor.h | 56 ++++++++++++++++ interface/src/ui/ApplicationOverlay.h | 1 + .../src/controllers/ScriptingInterface.cpp | 65 ------------------- .../src/controllers/ScriptingInterface.h | 43 ------------ .../src/AbstractViewStateInterface.h | 2 +- 12 files changed, 92 insertions(+), 141 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 92dc86ee02..4a0f3905f6 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -724,7 +724,7 @@ function MyController(hand) { } this.searchSphereOff(); - Controller.setReticleVisible(true); + Reticle.setVisible(true); }; @@ -1023,7 +1023,7 @@ function MyController(hand) { (this.triggerSmoothedGrab() || this.bumperSqueezed()) ? INTERSECT_COLOR : NO_INTERSECT_COLOR); } - Controller.setReticleVisible(false); + Reticle.setVisible(false); }; @@ -1886,7 +1886,7 @@ function cleanup() { rightController.cleanup(); leftController.cleanup(); Controller.disableMapping(MAPPING_NAME); - Controller.setReticleVisible(true); + Reticle.setVisible(true); } Script.scriptEnding.connect(cleanup); Script.update.connect(update); diff --git a/examples/controllers/philipsVersion.js b/examples/controllers/philipsVersion.js index 4ae617cf0b..ae4fb2ae8b 100644 --- a/examples/controllers/philipsVersion.js +++ b/examples/controllers/philipsVersion.js @@ -24,9 +24,9 @@ var PITCH_SCALING = 10.0; var YAW_SCALING = 10.0; var EXPECTED_CHANGE = 50; -var lastPos = Controller.getReticlePosition(); +var lastPos = Reticle.getPosition(); function moveReticle(dY, dX) { - var globalPos = Controller.getReticlePosition(); + var globalPos = Reticle.getPosition(); // some debugging to see if position is jumping around on us... var distanceSinceLastMove = length(lastPos, globalPos); @@ -45,7 +45,7 @@ function moveReticle(dY, dX) { globalPos.x += dX; globalPos.y += dY; - Controller.setReticlePosition(globalPos); + Reticle.setPosition(globalPos); lastPos = globalPos; } diff --git a/examples/controllers/reticleHandAngularVelocityTest.js b/examples/controllers/reticleHandAngularVelocityTest.js index 94288b7bfb..faefd3d3cf 100644 --- a/examples/controllers/reticleHandAngularVelocityTest.js +++ b/examples/controllers/reticleHandAngularVelocityTest.js @@ -31,9 +31,9 @@ function length(posA, posB) { } var EXPECTED_CHANGE = 50; -var lastPos = Controller.getReticlePosition(); +var lastPos = Reticle.getPosition(); function moveReticle(dX, dY) { - var globalPos = Controller.getReticlePosition(); + var globalPos = Reticle.getPosition(); // some debugging to see if position is jumping around on us... var distanceSinceLastMove = length(lastPos, globalPos); @@ -52,7 +52,7 @@ function moveReticle(dX, dY) { globalPos.x += dX; globalPos.y += dY; - Controller.setReticlePosition(globalPos); + Reticle.setPosition(globalPos); lastPos = globalPos; } diff --git a/examples/controllers/reticleHandRotationTest.js b/examples/controllers/reticleHandRotationTest.js index a27e6f2c4e..0f684a37f0 100644 --- a/examples/controllers/reticleHandRotationTest.js +++ b/examples/controllers/reticleHandRotationTest.js @@ -23,10 +23,10 @@ function length(posA, posB) { } function moveReticleAbsolute(x, y) { - var globalPos = Controller.getReticlePosition(); + var globalPos = Reticle.getPosition(); globalPos.x = x; globalPos.y = y; - Controller.setReticlePosition(globalPos); + Reticle.setPosition(globalPos); } var MAPPING_NAME = "com.highfidelity.testing.reticleWithHandRotation"; diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 461e5e56ba..144f8ad405 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -806,14 +806,14 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : } else if (action == controller::toInt(controller::Action::CYCLE_CAMERA)) { cycleCamera(); } else if (action == controller::toInt(controller::Action::CONTEXT_MENU)) { - auto reticlePosition = _controllerScriptingInterface->getReticlePosition(); + auto reticlePosition = _compositor.getReticlePosition(); offscreenUi->toggleMenu(_glWidget->mapFromGlobal(QPoint(reticlePosition.x, reticlePosition.y))); } else if (action == controller::toInt(controller::Action::RETICLE_X)) { - auto oldPos = _controllerScriptingInterface->getReticlePosition(); - _controllerScriptingInterface->setReticlePosition({ oldPos.x + state, oldPos.y }); + auto oldPos = _compositor.getReticlePosition(); + _compositor.setReticlePosition({ oldPos.x + state, oldPos.y }); } else if (action == controller::toInt(controller::Action::RETICLE_Y)) { - auto oldPos = _controllerScriptingInterface->getReticlePosition(); - _controllerScriptingInterface->setReticlePosition({ oldPos.x, oldPos.y + state }); + auto oldPos = _compositor.getReticlePosition(); + _compositor.setReticlePosition({ oldPos.x, oldPos.y + state }); } } }); @@ -1254,6 +1254,7 @@ void Application::initializeUi() { rootContext->setContextProperty("HMD", DependencyManager::get().data()); rootContext->setContextProperty("Scene", DependencyManager::get().data()); rootContext->setContextProperty("Render", _renderEngine->getConfiguration().get()); + rootContext->setContextProperty("Reticle", _compositor.getReticleInterface()); _glWidget->installEventFilter(offscreenUi.data()); offscreenUi->setMouseTranslator([=](const QPointF& pt) { @@ -2085,7 +2086,7 @@ void Application::keyPressEvent(QKeyEvent* event) { void Application::keyReleaseEvent(QKeyEvent* event) { if (event->key() == Qt::Key_Alt && _altPressed && hasFocus()) { auto offscreenUi = DependencyManager::get(); - auto reticlePosition = _controllerScriptingInterface->getReticlePosition(); + auto reticlePosition = _compositor.getReticlePosition(); offscreenUi->toggleMenu(_glWidget->mapFromGlobal(QPoint(reticlePosition.x, reticlePosition.y))); } @@ -2542,7 +2543,7 @@ void Application::setLowVelocityFilter(bool lowVelocityFilter) { controller::InputDevice::setLowVelocityFilter(lowVelocityFilter); } -ivec2 Application::getMouse() const { +ivec2 Application::getMouse() { if (isHMDMode()) { return _compositor.screenToOverlay(getTrueMouse()); } @@ -3566,7 +3567,7 @@ glm::vec3 Application::getSunDirection() { // FIXME, preprocessor guard this check to occur only in DEBUG builds static QThread * activeRenderingThread = nullptr; -PickRay Application::computePickRay(float x, float y) const { +PickRay Application::computePickRay(float x, float y) { vec2 pickPoint { x, y }; PickRay result; if (isHMDMode()) { @@ -4216,6 +4217,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("Render", _renderEngine->getConfiguration().get()); scriptEngine->registerGlobalObject("ScriptDiscoveryService", DependencyManager::get().data()); + scriptEngine->registerGlobalObject("Reticle", _compositor.getReticleInterface()); } bool Application::canAcceptURL(const QString& urlString) const { @@ -4695,7 +4697,7 @@ QSize Application::getDeviceSize() const { return fromGlm(getActiveDisplayPlugin()->getRecommendedRenderSize()); } -PickRay Application::computePickRay() const { +PickRay Application::computePickRay() { return computePickRay(getTrueMouse().x, getTrueMouse().y); } @@ -4703,9 +4705,9 @@ bool Application::isThrottleRendering() const { return getActiveDisplayPlugin()->isThrottled(); } -// FIXME -- consolidate users of getTrueMouse() controllerScriptingInterface->getReticlePosition() -ivec2 Application::getTrueMouse() const { - auto reticlePosition = _controllerScriptingInterface->getReticlePosition(); +// FIXME -- consolidate users of getTrueMouse() _compositor.getReticlePosition() +ivec2 Application::getTrueMouse() { + auto reticlePosition = _compositor.getReticlePosition(); return toGlm(_glWidget->mapFromGlobal(QPoint(reticlePosition.x, reticlePosition.y))); } diff --git a/interface/src/Application.h b/interface/src/Application.h index d5b677302a..1831f7171a 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -117,7 +117,7 @@ public: glm::uvec2 getUiSize() const; QSize getDeviceSize() const; bool hasFocus() const; - PickRay computePickRay() const; + PickRay computePickRay(); bool isThrottleRendering() const; @@ -139,8 +139,8 @@ public: EntityTreeRenderer* getEntityClipboardRenderer() { return &_entityClipboardRenderer; } EntityEditPacketSender* getEntityEditPacketSender() { return &_entityEditSender; } - ivec2 getMouse() const; - ivec2 getTrueMouse() const; + ivec2 getMouse(); + ivec2 getTrueMouse(); FaceTracker* getActiveFaceTracker(); FaceTracker* getSelectedFaceTracker(); @@ -169,7 +169,7 @@ public: virtual ViewFrustum* getCurrentViewFrustum() override { return getDisplayViewFrustum(); } virtual QThread* getMainThread() override { return thread(); } - virtual PickRay computePickRay(float x, float y) const override; + virtual PickRay computePickRay(float x, float y) override; virtual glm::vec3 getAvatarPosition() const override; virtual qreal getDevicePixelRatio() override; diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 736b1fffce..961f9df0fe 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -112,7 +112,9 @@ bool raySphereIntersect(const glm::vec3 &dir, const glm::vec3 &origin, float r, } ApplicationCompositor::ApplicationCompositor() : - _alphaPropertyAnimation(new QPropertyAnimation(this, "alpha")) + _alphaPropertyAnimation(new QPropertyAnimation(this, "alpha")), + _reticleInterface(new ReticleInterface(this)) + { auto geometryCache = DependencyManager::get(); @@ -282,15 +284,13 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int bindCursorTexture(batch); //Mouse Pointer - auto controllerScriptingInterface = DependencyManager::get(); - bool reticleVisible = controllerScriptingInterface->getReticleVisible(); - if (reticleVisible) { + if (getReticleVisible()) { glm::mat4 overlayXfm; _modelTransform.getMatrix(overlayXfm); glm::vec2 projection = screenToSpherical(qApp->getTrueMouse()); - float cursorDepth = controllerScriptingInterface->getReticleDepth(); + float cursorDepth = getReticleDepth(); mat4 pointerXfm = glm::scale(mat4(), vec3(cursorDepth)) * glm::mat4_cast(quat(vec3(-projection.y, projection.x, 0.0f))) * glm::translate(mat4(), vec3(0, 0, -1)); mat4 reticleXfm = overlayXfm * pointerXfm; reticleXfm = glm::scale(reticleXfm, reticleScale); diff --git a/interface/src/ui/ApplicationCompositor.h b/interface/src/ui/ApplicationCompositor.h index ae45352e84..fbac59a40c 100644 --- a/interface/src/ui/ApplicationCompositor.h +++ b/interface/src/ui/ApplicationCompositor.h @@ -9,6 +9,7 @@ #ifndef hifi_ApplicationCompositor_h #define hifi_ApplicationCompositor_h +#include #include #include #include @@ -22,6 +23,7 @@ class Camera; class PalmData; class RenderArgs; +class ReticleInterface; const float MAGNIFY_WIDTH = 220.0f; const float MAGNIFY_HEIGHT = 100.0f; @@ -80,6 +82,31 @@ public: static glm::vec2 screenToSpherical(const glm::vec2 & screenPos); static glm::vec2 sphericalToScreen(const glm::vec2 & sphericalPos); + Q_INVOKABLE bool getReticleVisible() { return _reticleVisible; } + Q_INVOKABLE void setReticleVisible(bool visible) { _reticleVisible = visible; } + + Q_INVOKABLE float getReticleDepth() { return _reticleDepth; } + Q_INVOKABLE void setReticleDepth(float depth) { _reticleDepth = depth; } + + Q_INVOKABLE glm::vec2 getReticlePosition() { + return toGlm(QCursor::pos()); + } + Q_INVOKABLE void setReticlePosition(glm::vec2 position) { + // NOTE: This is some debugging code we will leave in while debugging various reticle movement strategies, + // remove it after we're done + const float REASONABLE_CHANGE = 50.0f; + glm::vec2 oldPos = toGlm(QCursor::pos()); + auto distance = glm::distance(oldPos, position); + if (distance > REASONABLE_CHANGE) { + qDebug() << "Contrller::ScriptingInterface ---- UNREASONABLE CHANGE! distance:" << distance << " oldPos:" << oldPos << " newPos:" << position; + } + + QCursor::setPos(position.x, position.y); + } + + ReticleInterface* getReticleInterface() { return _reticleInterface; } + + private: void displayOverlayTextureStereo(RenderArgs* renderArgs, float aspectRatio, float fov); void bindCursorTexture(gpu::Batch& batch, uint8_t cursorId = 0); @@ -115,6 +142,35 @@ private: Transform _cameraBaseTransform; std::unique_ptr _alphaPropertyAnimation; + + bool _reticleVisible { true }; + float _reticleDepth { 1.0f }; + + ReticleInterface* _reticleInterface; + }; +// Scripting interface available to control the Reticle +class ReticleInterface : public QObject { + Q_OBJECT + Q_PROPERTY(glm::vec2 position READ getPosition WRITE setPosition) + Q_PROPERTY(bool visible READ getVisible WRITE setVisible) + Q_PROPERTY(float depth READ getDepth WRITE setDepth) +public: + ReticleInterface(ApplicationCompositor* outer) : _compositor(outer), QObject(outer) { } + + Q_INVOKABLE bool getVisible() { return _compositor->getReticleVisible(); } + Q_INVOKABLE void setVisible(bool visible) { _compositor->setReticleVisible(visible); } + + Q_INVOKABLE float getDepth() { return _compositor->getReticleDepth(); } + Q_INVOKABLE void setDepth(float depth) { _compositor->setReticleDepth(depth); } + + Q_INVOKABLE glm::vec2 getPosition() { return _compositor->getReticlePosition(); } + Q_INVOKABLE void setPosition(glm::vec2 position) { _compositor->setReticlePosition(position); } +private: + ApplicationCompositor* _compositor; +}; + + + #endif // hifi_ApplicationCompositor_h diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index 532fea23dc..d4a88afff5 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -14,6 +14,7 @@ #include + // Handles the drawing of the overlays to the screen // TODO, move divide up the rendering, displaying and input handling // facilities of this class diff --git a/libraries/controllers/src/controllers/ScriptingInterface.cpp b/libraries/controllers/src/controllers/ScriptingInterface.cpp index bc4b0469f5..275aeedb6b 100644 --- a/libraries/controllers/src/controllers/ScriptingInterface.cpp +++ b/libraries/controllers/src/controllers/ScriptingInterface.cpp @@ -106,71 +106,6 @@ namespace controller { return getPoseValue(Input(device, source, ChannelType::POSE).getID()); } - //bool ScriptingInterface::isPrimaryButtonPressed() const { - // return isButtonPressed(StandardButtonChannel::A); - //} - // - //glm::vec2 ScriptingInterface::getPrimaryJoystickPosition() const { - // return getJoystickPosition(0); - //} - - //int ScriptingInterface::getNumberOfButtons() const { - // return StandardButtonChannel::NUM_STANDARD_BUTTONS; - //} - - //bool ScriptingInterface::isButtonPressed(int buttonIndex) const { - // return getButtonValue((StandardButtonChannel)buttonIndex) == 0.0 ? false : true; - //} - - //int ScriptingInterface::getNumberOfTriggers() const { - // return StandardCounts::TRIGGERS; - //} - - //float ScriptingInterface::getTriggerValue(int triggerIndex) const { - // return getAxisValue(triggerIndex == 0 ? StandardAxisChannel::LT : StandardAxisChannel::RT); - //} - - //int ScriptingInterface::getNumberOfJoysticks() const { - // return StandardCounts::ANALOG_STICKS; - //} - - //glm::vec2 ScriptingInterface::getJoystickPosition(int joystickIndex) const { - // StandardAxisChannel xid = StandardAxisChannel::LX; - // StandardAxisChannel yid = StandardAxisChannel::LY; - // if (joystickIndex != 0) { - // xid = StandardAxisChannel::RX; - // yid = StandardAxisChannel::RY; - // } - // vec2 result; - // result.x = getAxisValue(xid); - // result.y = getAxisValue(yid); - // return result; - //} - - //int ScriptingInterface::getNumberOfSpatialControls() const { - // return StandardCounts::POSES; - //} - - //glm::vec3 ScriptingInterface::getSpatialControlPosition(int controlIndex) const { - // // FIXME extract the position from the standard pose - // return vec3(); - //} - - //glm::vec3 ScriptingInterface::getSpatialControlVelocity(int controlIndex) const { - // // FIXME extract the velocity from the standard pose - // return vec3(); - //} - - //glm::vec3 ScriptingInterface::getSpatialControlNormal(int controlIndex) const { - // // FIXME extract the normal from the standard pose - // return vec3(); - //} - // - //glm::quat ScriptingInterface::getSpatialControlRawRotation(int controlIndex) const { - // // FIXME extract the rotation from the standard pose - // return quat(); - //} - QVector ScriptingInterface::getAllActions() { return DependencyManager::get()->getAllActions(); } diff --git a/libraries/controllers/src/controllers/ScriptingInterface.h b/libraries/controllers/src/controllers/ScriptingInterface.h index ad1197e3f0..33eaa0c702 100644 --- a/libraries/controllers/src/controllers/ScriptingInterface.h +++ b/libraries/controllers/src/controllers/ScriptingInterface.h @@ -90,46 +90,6 @@ namespace controller { Q_INVOKABLE QObject* parseMapping(const QString& json); Q_INVOKABLE QObject* loadMapping(const QString& jsonUrl); - Q_INVOKABLE bool getReticleVisible() { return _reticleVisible; } - Q_INVOKABLE void setReticleVisible(bool visible) { _reticleVisible = visible; } - - Q_INVOKABLE float getReticleDepth() { return _reticleDepth; } - Q_INVOKABLE void setReticleDepth(float depth) { _reticleDepth = depth; } - - Q_INVOKABLE glm::vec2 getReticlePosition() { - return toGlm(QCursor::pos()); - } - Q_INVOKABLE void setReticlePosition(glm::vec2 position) { - // NOTE: This is some debugging code we will leave in while debugging various reticle movement strategies, - // remove it after we're done - const float REASONABLE_CHANGE = 50.0f; - glm::vec2 oldPos = toGlm(QCursor::pos()); - auto distance = glm::distance(oldPos, position); - if (distance > REASONABLE_CHANGE) { - qDebug() << "Contrller::ScriptingInterface ---- UNREASONABLE CHANGE! distance:" << distance << " oldPos:" << oldPos << " newPos:" << position; - } - - QCursor::setPos(position.x, position.y); - } - - //Q_INVOKABLE bool isPrimaryButtonPressed() const; - //Q_INVOKABLE glm::vec2 getPrimaryJoystickPosition() const; - - //Q_INVOKABLE int getNumberOfButtons() const; - //Q_INVOKABLE bool isButtonPressed(int buttonIndex) const; - - //Q_INVOKABLE int getNumberOfTriggers() const; - //Q_INVOKABLE float getTriggerValue(int triggerIndex) const; - - //Q_INVOKABLE int getNumberOfJoysticks() const; - //Q_INVOKABLE glm::vec2 getJoystickPosition(int joystickIndex) const; - - //Q_INVOKABLE int getNumberOfSpatialControls() const; - //Q_INVOKABLE glm::vec3 getSpatialControlPosition(int controlIndex) const; - //Q_INVOKABLE glm::vec3 getSpatialControlVelocity(int controlIndex) const; - //Q_INVOKABLE glm::vec3 getSpatialControlNormal(int controlIndex) const; - //Q_INVOKABLE glm::quat getSpatialControlRawRotation(int controlIndex) const; - Q_INVOKABLE const QVariantMap& getHardware() { return _hardware; } Q_INVOKABLE const QVariantMap& getActions() { return _actions; } Q_INVOKABLE const QVariantMap& getStandard() { return _standard; } @@ -170,9 +130,6 @@ namespace controller { bool _touchCaptured{ false }; bool _wheelCaptured{ false }; bool _actionsCaptured{ false }; - - bool _reticleVisible{ true }; - float _reticleDepth { 1.0f }; }; diff --git a/libraries/render-utils/src/AbstractViewStateInterface.h b/libraries/render-utils/src/AbstractViewStateInterface.h index 815cb45423..1165816dd2 100644 --- a/libraries/render-utils/src/AbstractViewStateInterface.h +++ b/libraries/render-utils/src/AbstractViewStateInterface.h @@ -36,7 +36,7 @@ public: virtual QThread* getMainThread() = 0; - virtual PickRay computePickRay(float x, float y) const = 0; + virtual PickRay computePickRay(float x, float y) = 0; virtual glm::vec3 getAvatarPosition() const = 0; From 983a0ccb9b7b414bfba08eec8a20c1e1caf96944 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Tue, 16 Feb 2016 18:00:39 -0800 Subject: [PATCH 05/72] Change internal preference names so that old users pick up the new default values, and change name in dialog. --- interface/src/ui/PreferencesDialog.cpp | 2 +- libraries/audio-client/src/AudioClient.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index b1812b7bd3..fad1b6be31 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -270,7 +270,7 @@ void setupPreferences() { { auto getter = []()->float { return DependencyManager::get()->getOutputBufferSize(); }; auto setter = [](float value) { DependencyManager::get()->setOutputBufferSize(value); }; - auto preference = new SpinnerPreference(AUDIO, "Output Buffer Size (frames)", getter, setter); + auto preference = new SpinnerPreference(AUDIO, "Output Buffer Initial Size (frames)", getter, setter); preference->setMin(1); preference->setMax(20); preference->setStep(1); diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index f7dc0c65bb..bcd9c91b24 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -80,9 +80,9 @@ AudioClient::AudioClient() : _isStereoInput(false), _outputStarveDetectionStartTimeMsec(0), _outputStarveDetectionCount(0), - _outputBufferSizeFrames("audioOutputBufferSize", DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES), + _outputBufferSizeFrames("audioOutputBufferSizeFrames", DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES), _sessionOutputBufferSizeFrames(_outputBufferSizeFrames.get()), - _outputStarveDetectionEnabled("audioOutputStarveDetectionEnabled", + _outputStarveDetectionEnabled("audioOutputBufferStarveDetectionEnabled", DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_ENABLED), _outputStarveDetectionPeriodMsec("audioOutputStarveDetectionPeriod", DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_PERIOD), From 3426173d1d1bb311dc05e9ca9e018b089fa30152 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 17 Feb 2016 11:44:11 -0800 Subject: [PATCH 06/72] AnimInverseKinematics: open up shoulder swing constraint. --- libraries/animation/src/AnimInverseKinematics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index ff1dea3d48..48ad9b852d 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -670,7 +670,7 @@ void AnimInverseKinematics::initConstraints() { stConstraint->setTwistLimits(-MAX_SHOULDER_TWIST, MAX_SHOULDER_TWIST); std::vector minDots; - const float MAX_SHOULDER_SWING = PI / 20.0f; + const float MAX_SHOULDER_SWING = PI / 6.0f; minDots.push_back(cosf(MAX_SHOULDER_SWING)); stConstraint->setSwingLimits(minDots); From b8b1565470f59bfa1febdc92877eaf64d5d67317 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Wed, 17 Feb 2016 13:46:48 -0800 Subject: [PATCH 07/72] Don't fake-fail the format test. Trust the os. --- libraries/audio-client/src/AudioClient.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index f7dc0c65bb..9037b4ccc7 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -278,9 +278,9 @@ QAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) { bool adjustedFormatForAudioDevice(const QAudioDeviceInfo& audioDevice, const QAudioFormat& desiredAudioFormat, QAudioFormat& adjustedAudioFormat) { - // FIXME: directly using 24khz has a bug somewhere that causes channels to be swapped. - // Continue using our internal resampler, for now. - if (true || !audioDevice.isFormatSupported(desiredAudioFormat)) { + // There had been a note here that 2khz was swapping channels. That doesn't seem to be happening + // any more for me. If it does, then we'll want to always resample. + if (!audioDevice.isFormatSupported(desiredAudioFormat)) { qCDebug(audioclient) << "The desired format for audio I/O is" << desiredAudioFormat; qCDebug(audioclient, "The desired audio format is not supported by this device"); @@ -288,7 +288,7 @@ bool adjustedFormatForAudioDevice(const QAudioDeviceInfo& audioDevice, adjustedAudioFormat = desiredAudioFormat; adjustedAudioFormat.setChannelCount(2); - if (false && audioDevice.isFormatSupported(adjustedAudioFormat)) { + if (audioDevice.isFormatSupported(adjustedAudioFormat)) { return true; } else { adjustedAudioFormat.setChannelCount(1); @@ -975,8 +975,7 @@ void AudioClient::outputNotify() { int oldOutputBufferSizeFrames = _sessionOutputBufferSizeFrames; int newOutputBufferSizeFrames = setOutputBufferSize(oldOutputBufferSizeFrames + 1, false); if (newOutputBufferSizeFrames > oldOutputBufferSizeFrames) { - qCDebug(audioclient) << "Starve detection threshold met, increasing buffer size to " << newOutputBufferSizeFrames << - "on period size" << _audioOutput->periodSize() << "bytes."; + qCDebug(audioclient) << "Starve detection threshold met, increasing buffer size to " << newOutputBufferSizeFrames; } } } @@ -1038,16 +1037,20 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDevice // setup our general output device for audio-mixer audio _audioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this); - _audioOutput->setBufferSize(_sessionOutputBufferSizeFrames *_outputFrameSize * sizeof(int16_t)); + int osDefaultBufferSize = _audioOutput->bufferSize(); + int requestedSize = _sessionOutputBufferSizeFrames *_outputFrameSize * sizeof(int16_t); + _audioOutput->setBufferSize(requestedSize); connect(_audioOutput, &QAudioOutput::notify, this, &AudioClient::outputNotify); connect(this, &AudioClient::changeDevice, this, [=](const QAudioDeviceInfo& outputDeviceInfo) { switchOutputToAudioDevice(outputDeviceInfo); }); - qCDebug(audioclient) << "Output Buffer capacity in frames: " << _audioOutput->bufferSize() / sizeof(int16_t) / (float)_outputFrameSize; - _audioOutputIODevice.start(); _audioOutput->start(&_audioOutputIODevice); + qCDebug(audioclient) << "Output Buffer capacity in frames: " << _audioOutput->bufferSize() / sizeof(int16_t) / (float)_outputFrameSize << + "requested bytes:" << requestedSize << "actual bytes:" << _audioOutput->bufferSize() << + "os default:" << osDefaultBufferSize << "period size:" << _audioOutput->periodSize(); + // setup a loopback audio output device _loopbackAudioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this); From 73ac47724af70abf2fd7a3739f20adbd1701133b Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 17 Feb 2016 16:23:18 -0800 Subject: [PATCH 08/72] Rig: Prevent the hand IK targets from entering the body. Use a 2d circle/circle intersection test to keep the hands outside of the body. --- interface/src/avatar/SkeletonModel.cpp | 1 + libraries/animation/src/Rig.cpp | 39 +++++++++++++++++++-- libraries/animation/src/Rig.h | 1 + libraries/physics/src/CharacterController.h | 2 ++ 4 files changed, 41 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index c77c4fdd78..e4c98215c2 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -144,6 +144,7 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { } else { handParams.isRightEnabled = false; } + handParams.bodyCapsuleRadius = myAvatar->getCharacterController()->getCapsuleRadius(); _rig->updateFromHandParameters(handParams, deltaTime); diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 817054a9f5..718ae9bb79 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1080,8 +1080,29 @@ void Rig::updateEyeJoint(int index, const glm::vec3& modelTranslation, const glm void Rig::updateFromHandParameters(const HandParameters& params, float dt) { if (_animSkeleton && _animNode) { + + const float HAND_RADIUS = 0.05f; + const float BODY_RADIUS = params.bodyCapsuleRadius; + + // project the hips onto the xz plane. + auto hipsTrans = _internalPoseSet._absolutePoses[_animSkeleton->nameToJointIndex("Hips")].trans; + const glm::vec2 bodyCircleCenter(hipsTrans.x, hipsTrans.z); + if (params.isLeftEnabled) { - _animVars.set("leftHandPosition", params.leftPosition); + + // project the hand position onto the xz plane. + glm::vec2 handCircleCenter(params.leftPosition.x, params.leftPosition.z); + auto d = handCircleCenter - bodyCircleCenter; + + // check for 2d overlap of the hand and body circles. + float penetrationDistance = HAND_RADIUS + BODY_RADIUS - glm::length(d); + if (penetrationDistance > 0) { + // push the hands out of the body + handCircleCenter += penetrationDistance * glm::normalize(d); + } + + glm::vec3 handPosition(handCircleCenter.x, params.leftPosition.y, handCircleCenter.y); + _animVars.set("leftHandPosition", handPosition); _animVars.set("leftHandRotation", params.leftOrientation); _animVars.set("leftHandType", (int)IKTarget::Type::RotationAndPosition); } else { @@ -1089,8 +1110,22 @@ void Rig::updateFromHandParameters(const HandParameters& params, float dt) { _animVars.unset("leftHandRotation"); _animVars.set("leftHandType", (int)IKTarget::Type::HipsRelativeRotationAndPosition); } + if (params.isRightEnabled) { - _animVars.set("rightHandPosition", params.rightPosition); + + // project the hand position onto the xz plane. + glm::vec2 handCircleCenter(params.rightPosition.x, params.rightPosition.z); + auto d = handCircleCenter - bodyCircleCenter; + + // check for 2d overlap of the hand and body circles. + float penetrationDistance = HAND_RADIUS + BODY_RADIUS - glm::length(d); + if (penetrationDistance > 0) { + // push the hands out of the body + handCircleCenter += penetrationDistance * glm::normalize(d); + } + + glm::vec3 handPosition(handCircleCenter.x, params.rightPosition.y, handCircleCenter.y); + _animVars.set("rightHandPosition", handPosition); _animVars.set("rightHandRotation", params.rightOrientation); _animVars.set("rightHandType", (int)IKTarget::Type::RotationAndPosition); } else { diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index e4668d6c2a..9c5b014d55 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -67,6 +67,7 @@ public: struct HandParameters { bool isLeftEnabled; bool isRightEnabled; + float bodyCapsuleRadius; glm::vec3 leftPosition = glm::vec3(); // rig space glm::quat leftOrientation = glm::quat(); // rig space (z forward) glm::vec3 rightPosition = glm::vec3(); // rig space diff --git a/libraries/physics/src/CharacterController.h b/libraries/physics/src/CharacterController.h index 5362ca52e4..a8543d6070 100644 --- a/libraries/physics/src/CharacterController.h +++ b/libraries/physics/src/CharacterController.h @@ -78,6 +78,8 @@ public: glm::vec3 getLinearVelocity() const; + float getCapsuleRadius() const { return _radius; } + enum class State { Ground = 0, Takeoff, From 8b8b99c7e02817d67bd2d7f2c5ade098814a9467 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Wed, 17 Feb 2016 21:19:01 -0800 Subject: [PATCH 09/72] HMD mouse checkpoint --- interface/src/Application.cpp | 107 +++++++++++++----- interface/src/Application.h | 15 ++- .../ControllerScriptingInterface.cpp | 8 +- .../scripting/ControllerScriptingInterface.h | 16 +-- interface/src/ui/ApplicationCompositor.cpp | 94 ++++++++++++++- interface/src/ui/ApplicationCompositor.h | 35 +++--- .../src/EntityTreeRenderer.cpp | 64 +++++------ .../src/EntityTreeRenderer.h | 14 +-- .../src/RenderableWebEntityItem.cpp | 2 +- .../src/input-plugins/KeyboardMouseDevice.cpp | 6 +- .../src/input-plugins/KeyboardMouseDevice.h | 6 +- libraries/script-engine/src/MouseEvent.cpp | 4 +- libraries/script-engine/src/MouseEvent.h | 3 +- 13 files changed, 260 insertions(+), 114 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 144f8ad405..9235f20a89 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -786,8 +786,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : } if (action == controller::toInt(controller::Action::RETICLE_CLICK)) { - auto globalPos = QCursor::pos(); - auto localPos = _glWidget->mapFromGlobal(globalPos); + auto reticlePos = _compositor.getReticlePosition(); + QPoint globalPos(reticlePos.x, reticlePos.y); + + // FIXME - it would be nice if this was self contained in the _compositor or Reticle class + auto localPos = isHMDMode() ? globalPos : _glWidget->mapFromGlobal(globalPos); if (state) { QMouseEvent mousePress(QEvent::MouseButtonPress, localPos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); sendEvent(_glWidget, &mousePress); @@ -809,9 +812,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : auto reticlePosition = _compositor.getReticlePosition(); offscreenUi->toggleMenu(_glWidget->mapFromGlobal(QPoint(reticlePosition.x, reticlePosition.y))); } else if (action == controller::toInt(controller::Action::RETICLE_X)) { + qDebug() << "Action::RETICLE_X..."; auto oldPos = _compositor.getReticlePosition(); _compositor.setReticlePosition({ oldPos.x + state, oldPos.y }); } else if (action == controller::toInt(controller::Action::RETICLE_Y)) { + qDebug() << "Action::RETICLE_Y..."; auto oldPos = _compositor.getReticlePosition(); _compositor.setReticlePosition({ oldPos.x, oldPos.y + state }); } @@ -955,7 +960,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : // If the user clicks somewhere where there is NO entity at all, we will release focus connect(getEntities(), &EntityTreeRenderer::mousePressOffEntity, - [=](const RayToEntityIntersectionResult& entityItemID, const QMouseEvent* event, unsigned int deviceId) { + [=](const RayToEntityIntersectionResult& entityItemID, const QMouseEvent* event) { _keyboardFocusedItem = UNKNOWN_ENTITY_ID; if (_keyboardFocusHighlight) { _keyboardFocusHighlight->setVisible(false); @@ -1261,7 +1266,8 @@ void Application::initializeUi() { QPointF result = pt; auto displayPlugin = getActiveDisplayPlugin(); if (displayPlugin->isHmd()) { - auto resultVec = _compositor.screenToOverlay(toGlm(pt)); + auto fakeScreen = _compositor.getReticlePosition(); + auto resultVec = _compositor.screenToOverlay(fakeScreen); // toGlm(pt)); result = QPointF(resultVec.x, resultVec.y); } return result.toPoint(); @@ -1736,6 +1742,7 @@ bool Application::event(QEvent* event) { switch (event->type()) { case QEvent::MouseMove: + qDebug() << __FUNCTION__ << "(QEvent::MouseMove)... line:" << __LINE__; mouseMoveEvent((QMouseEvent*)event); return true; case QEvent::MouseButtonPress: @@ -1772,6 +1779,9 @@ bool Application::event(QEvent* event) { case QEvent::Drop: dropEvent(static_cast(event)); return true; + case QEvent::Leave: + qDebug() << __FUNCTION__ << "().... QEvent::Leave"; + break; // fall through default: break; } @@ -1800,6 +1810,12 @@ bool Application::event(QEvent* event) { } bool Application::eventFilter(QObject* object, QEvent* event) { + + if (event->type() == QEvent::Leave) { + qDebug() << __FUNCTION__ << "().... QEvent::Leave"; + _compositor.handleLeaveEvent(); + } + if (event->type() == QEvent::ShortcutOverride) { if (DependencyManager::get()->shouldSwallowShortcut(event)) { event->accept(); @@ -2152,13 +2168,7 @@ void Application::focusOutEvent(QFocusEvent* event) { _keysPressed.clear(); } -void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) { - PROFILE_RANGE(__FUNCTION__); - - if (_aboutToQuit) { - return; - } - +void Application::maybeToggleMenuVisible(QMouseEvent* event) { #ifndef Q_OS_MAC // If in full screen, and our main windows menu bar is hidden, and we're close to the top of the QMainWindow // then show the menubar. @@ -2170,7 +2180,7 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) { if (event->pos().y() <= MENU_TOGGLE_AREA) { menuBar->setVisible(true); } - } else { + } else { if (event->pos().y() > MENU_TOGGLE_AREA) { menuBar->setVisible(false); } @@ -2178,9 +2188,38 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) { } } #endif +} + +/// called by ApplicationCompositor when in HMD mode and we're faking our mouse movement +void Application::fakeMouseEvent(QMouseEvent* event) { + _fakedMouseEvent = true; + sendEvent(_glWidget, event); + _fakedMouseEvent = false; +} + +void Application::mouseMoveEvent(QMouseEvent* event) { + PROFILE_RANGE(__FUNCTION__); + + if (_aboutToQuit) { + return; + } + qDebug() << __FUNCTION__ << "line:" << __LINE__ << "event:" << event << "_fakedMouseEvent:" << _fakedMouseEvent; + + maybeToggleMenuVisible(event); + + // if this is a real mouse event, and we're in HMD mode, then we should use it to move the + // compositor reticle + if (!_fakedMouseEvent && isHMDMode()) { + _compositor.handleRealMouseMoveEvent(event); + return; // bail + } + if (!_fakedMouseEvent) { + _compositor.trackRealMouseMoveEvent(event); // FIXME - super janky + } auto offscreenUi = DependencyManager::get(); - QPointF transformedPos = offscreenUi->mapToVirtualScreen(event->localPos(), _glWidget); + auto eventPosition = _compositor.getMouseEventPosition(event); + QPointF transformedPos = offscreenUi->mapToVirtualScreen(eventPosition, _glWidget); auto button = event->button(); auto buttons = event->buttons(); // Determine if the ReticleClick Action is 1 and if so, fake include the LeftMouseButton @@ -2196,21 +2235,21 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) { event->screenPos(), button, buttons, event->modifiers()); - getEntities()->mouseMoveEvent(&mappedEvent, deviceID); - _controllerScriptingInterface->emitMouseMoveEvent(&mappedEvent, deviceID); // send events to any registered scripts + getEntities()->mouseMoveEvent(&mappedEvent); + _controllerScriptingInterface->emitMouseMoveEvent(&mappedEvent); // send events to any registered scripts // if one of our scripts have asked to capture this event, then stop processing it if (_controllerScriptingInterface->isMouseCaptured()) { return; } - if (deviceID == 0 && Menu::getInstance()->isOptionChecked(KeyboardMouseDevice::NAME)) { - _keyboardMouseDevice->mouseMoveEvent(event, deviceID); + if (Menu::getInstance()->isOptionChecked(KeyboardMouseDevice::NAME)) { + _keyboardMouseDevice->mouseMoveEvent(event); } } -void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { +void Application::mousePressEvent(QMouseEvent* event) { // Inhibit the menu if the user is using alt-mouse dragging _altPressed = false; @@ -2220,14 +2259,21 @@ void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { // keyboard shortcuts not to be swallowed by them. In particular, WebEngineViews // will consume all keyboard events. offscreenUi->unfocusWindows(); - QPointF transformedPos = offscreenUi->mapToVirtualScreen(event->localPos(), _glWidget); + qDebug() << __FUNCTION__ << "event:" << event; + + auto eventPosition = _compositor.getMouseEventPosition(event); + QPointF transformedPos = offscreenUi->mapToVirtualScreen(eventPosition, _glWidget); + + qDebug() << __FUNCTION__ << " eventPosition:" << eventPosition; + qDebug() << __FUNCTION__ << "transformedPos:" << transformedPos; + QMouseEvent mappedEvent(event->type(), transformedPos, event->screenPos(), event->button(), event->buttons(), event->modifiers()); if (!_aboutToQuit) { - getEntities()->mousePressEvent(&mappedEvent, deviceID); + getEntities()->mousePressEvent(&mappedEvent); } _controllerScriptingInterface->emitMousePressEvent(&mappedEvent); // send events to any registered scripts @@ -2239,7 +2285,7 @@ void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { if (hasFocus()) { - if (deviceID == 0 && Menu::getInstance()->isOptionChecked(KeyboardMouseDevice::NAME)) { + if (Menu::getInstance()->isOptionChecked(KeyboardMouseDevice::NAME)) { _keyboardMouseDevice->mousePressEvent(event); } @@ -2253,7 +2299,7 @@ void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { } } -void Application::mouseDoublePressEvent(QMouseEvent* event, unsigned int deviceID) { +void Application::mouseDoublePressEvent(QMouseEvent* event) { // if one of our scripts have asked to capture this event, then stop processing it if (_controllerScriptingInterface->isMouseCaptured()) { return; @@ -2262,17 +2308,18 @@ void Application::mouseDoublePressEvent(QMouseEvent* event, unsigned int deviceI _controllerScriptingInterface->emitMouseDoublePressEvent(event); } -void Application::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) { +void Application::mouseReleaseEvent(QMouseEvent* event) { auto offscreenUi = DependencyManager::get(); - QPointF transformedPos = offscreenUi->mapToVirtualScreen(event->localPos(), _glWidget); + auto eventPosition = _compositor.getMouseEventPosition(event); + QPointF transformedPos = offscreenUi->mapToVirtualScreen(eventPosition, _glWidget); QMouseEvent mappedEvent(event->type(), transformedPos, event->screenPos(), event->button(), event->buttons(), event->modifiers()); if (!_aboutToQuit) { - getEntities()->mouseReleaseEvent(&mappedEvent, deviceID); + getEntities()->mouseReleaseEvent(&mappedEvent); } _controllerScriptingInterface->emitMouseReleaseEvent(&mappedEvent); // send events to any registered scripts @@ -2283,7 +2330,7 @@ void Application::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) { } if (hasFocus()) { - if (deviceID == 0 && Menu::getInstance()->isOptionChecked(KeyboardMouseDevice::NAME)) { + if (Menu::getInstance()->isOptionChecked(KeyboardMouseDevice::NAME)) { _keyboardMouseDevice->mouseReleaseEvent(event); } @@ -4689,6 +4736,14 @@ glm::uvec2 Application::getCanvasSize() const { return glm::uvec2(_glWidget->width(), _glWidget->height()); } +QRect Application::getApplicationGeometry() const { + auto geometry = _glWidget->geometry(); + auto topLeft = geometry.topLeft(); + auto topLeftScreen = _glWidget->mapToGlobal(topLeft); + geometry.moveTopLeft(topLeftScreen); + return geometry; +} + glm::uvec2 Application::getUiSize() const { return getActiveDisplayPlugin()->getRecommendedUiSize(); } diff --git a/interface/src/Application.h b/interface/src/Application.h index 1831f7171a..f05c5c6123 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -114,6 +114,8 @@ public: bool eventFilter(QObject* object, QEvent* event) override; glm::uvec2 getCanvasSize() const; + QRect getApplicationGeometry() const; + glm::uvec2 getUiSize() const; QSize getDeviceSize() const; bool hasFocus() const; @@ -219,6 +221,8 @@ public: float getAverageSimsPerSecond(); + void fakeMouseEvent(QMouseEvent* event); + signals: void svoImportRequested(const QString& url); @@ -368,10 +372,10 @@ private: void focusOutEvent(QFocusEvent* event); void focusInEvent(QFocusEvent* event); - void mouseMoveEvent(QMouseEvent* event, unsigned int deviceID = 0); - void mousePressEvent(QMouseEvent* event, unsigned int deviceID = 0); - void mouseDoublePressEvent(QMouseEvent* event, unsigned int deviceID = 0); - void mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID = 0); + void mouseMoveEvent(QMouseEvent* event); + void mousePressEvent(QMouseEvent* event); + void mouseDoublePressEvent(QMouseEvent* event); + void mouseReleaseEvent(QMouseEvent* event); void touchBeginEvent(QTouchEvent* event); void touchEndEvent(QTouchEvent* event); @@ -381,6 +385,7 @@ private: void dropEvent(QDropEvent* event); void dragEnterEvent(QDragEnterEvent* event); + void maybeToggleMenuVisible(QMouseEvent* event); bool _dependencyManagerIsSetup; @@ -510,6 +515,8 @@ private: bool _settingsLoaded { false }; bool _pendingPaint { false }; QTimer* _idleTimer { nullptr }; + + bool _fakedMouseEvent { false }; }; #endif // hifi_Application_h diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index 3bcf8bb311..9ca1e2c6c6 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -164,10 +164,10 @@ InputController::Key InputController::getKey() const { void ControllerScriptingInterface::emitKeyPressEvent(QKeyEvent* event) { emit keyPressEvent(KeyEvent(*event)); } void ControllerScriptingInterface::emitKeyReleaseEvent(QKeyEvent* event) { emit keyReleaseEvent(KeyEvent(*event)); } -void ControllerScriptingInterface::emitMouseMoveEvent(QMouseEvent* event, unsigned int deviceID) { emit mouseMoveEvent(MouseEvent(*event, deviceID)); } -void ControllerScriptingInterface::emitMousePressEvent(QMouseEvent* event, unsigned int deviceID) { emit mousePressEvent(MouseEvent(*event, deviceID)); } -void ControllerScriptingInterface::emitMouseDoublePressEvent(QMouseEvent* event, unsigned int deviceID) { emit mouseDoublePressEvent(MouseEvent(*event, deviceID)); } -void ControllerScriptingInterface::emitMouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) { emit mouseReleaseEvent(MouseEvent(*event, deviceID)); } +void ControllerScriptingInterface::emitMouseMoveEvent(QMouseEvent* event) { emit mouseMoveEvent(MouseEvent(*event)); } +void ControllerScriptingInterface::emitMousePressEvent(QMouseEvent* event) { emit mousePressEvent(MouseEvent(*event)); } +void ControllerScriptingInterface::emitMouseDoublePressEvent(QMouseEvent* event) { emit mouseDoublePressEvent(MouseEvent(*event)); } +void ControllerScriptingInterface::emitMouseReleaseEvent(QMouseEvent* event) { emit mouseReleaseEvent(MouseEvent(*event)); } void ControllerScriptingInterface::emitTouchBeginEvent(const TouchEvent& event) { emit touchBeginEvent(event); } void ControllerScriptingInterface::emitTouchEndEvent(const TouchEvent& event) { emit touchEndEvent(event); } diff --git a/interface/src/scripting/ControllerScriptingInterface.h b/interface/src/scripting/ControllerScriptingInterface.h index 8bd698cfb2..43bb6987db 100644 --- a/interface/src/scripting/ControllerScriptingInterface.h +++ b/interface/src/scripting/ControllerScriptingInterface.h @@ -70,10 +70,10 @@ public: void handleMetaEvent(HFMetaEvent* event); - void emitMouseMoveEvent(QMouseEvent* event, unsigned int deviceID = 0); - void emitMousePressEvent(QMouseEvent* event, unsigned int deviceID = 0); - void emitMouseDoublePressEvent(QMouseEvent* event, unsigned int deviceID = 0); - void emitMouseReleaseEvent(QMouseEvent* event, unsigned int deviceID = 0); + void emitMouseMoveEvent(QMouseEvent* event); + void emitMousePressEvent(QMouseEvent* event); + void emitMouseDoublePressEvent(QMouseEvent* event); + void emitMouseReleaseEvent(QMouseEvent* event); void emitTouchBeginEvent(const TouchEvent& event); void emitTouchEndEvent(const TouchEvent& event); @@ -111,10 +111,10 @@ signals: void backStartEvent(); void backEndEvent(); - void mouseMoveEvent(const MouseEvent& event, unsigned int deviceID = 0); - void mousePressEvent(const MouseEvent& event, unsigned int deviceID = 0); - void mouseDoublePressEvent(const MouseEvent& event, unsigned int deviceID = 0); - void mouseReleaseEvent(const MouseEvent& event, unsigned int deviceID = 0); + void mouseMoveEvent(const MouseEvent& event); + void mousePressEvent(const MouseEvent& event); + void mouseDoublePressEvent(const MouseEvent& event); + void mouseReleaseEvent(const MouseEvent& event); void touchBeginEvent(const TouchEvent& event); void touchEndEvent(const TouchEvent& event); diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 961f9df0fe..806435a6c2 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -216,7 +216,7 @@ void ApplicationCompositor::displayOverlayTexture(RenderArgs* renderArgs) { //draw the mouse pointer // Get the mouse coordinates and convert to NDC [-1, 1] - vec2 canvasSize = qApp->getCanvasSize(); + vec2 canvasSize = qApp->getCanvasSize(); // desktop, use actual canvas... vec2 mousePosition = toNormalizedDeviceScale(vec2(qApp->getMouse()), canvasSize); // Invert the Y axis mousePosition.y *= -1.0f; @@ -246,7 +246,8 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int updateTooltips(); - vec2 canvasSize = qApp->getCanvasSize(); + glm::uvec2 screenSize { VIRTUAL_SCREEN_SIZE_X, VIRTUAL_SCREEN_SIZE_Y }; // = qApp->getCanvasSize(); // HMD use virtual screen size + vec2 canvasSize = screenSize; _textureAspectRatio = aspect(canvasSize); auto geometryCache = DependencyManager::get(); @@ -288,8 +289,9 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int glm::mat4 overlayXfm; _modelTransform.getMatrix(overlayXfm); - glm::vec2 projection = screenToSpherical(qApp->getTrueMouse()); - + auto reticlePosition = getReticlePosition(); + //qDebug() << "reticlePosition:" << reticlePosition; // FIXME - remove this debugging + glm::vec2 projection = screenToSpherical(reticlePosition); float cursorDepth = getReticleDepth(); mat4 pointerXfm = glm::scale(mat4(), vec3(cursorDepth)) * glm::mat4_cast(quat(vec3(-projection.y, projection.x, 0.0f))) * glm::translate(mat4(), vec3(0, 0, -1)); mat4 reticleXfm = overlayXfm * pointerXfm; @@ -300,6 +302,85 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int }); } +QPointF ApplicationCompositor::getMouseEventPosition(QMouseEvent* event) { + if (qApp->isHMDMode()) { + return QPointF(_reticlePositionInHMD.x, _reticlePositionInHMD.y); + } + return event->localPos(); +} + + +void ApplicationCompositor::handleLeaveEvent() { + if (qApp->isHMDMode()) { + auto applicationGeometry = qApp->getApplicationGeometry(); + qDebug() << "SENDING mouse back to center:" << applicationGeometry.center(); + _ignoreMouseMove = true; + auto sendToPos = applicationGeometry.center(); + QCursor::setPos(sendToPos); + _lastKnownRealMouse = sendToPos; + } +} + +void ApplicationCompositor::trackRealMouseMoveEvent(QMouseEvent* event) { + qDebug() << __FUNCTION__ << "() BEFORE _lastKnownRealMouse:" << _lastKnownRealMouse; + _lastKnownRealMouse = QCursor::pos(); + qDebug() << __FUNCTION__ << "() AFTER _lastKnownRealMouse:" << _lastKnownRealMouse; +} + +void ApplicationCompositor::handleRealMouseMoveEvent(QMouseEvent* event) { + qDebug() << __FUNCTION__ << "() event:" << event; + if (_ignoreMouseMove) { + qDebug() << __FUNCTION__ << "() IGNORE MOUSE MOVE!!!"; + _ignoreMouseMove = false; + return; + } + + auto applicationGeometry = qApp->getApplicationGeometry(); + qDebug() << ".... applicationGeometry:" << applicationGeometry; + + auto newPosition = QCursor::pos(); + auto changeInRealMouse = newPosition - _lastKnownRealMouse; + qDebug() << __FUNCTION__ << "() ..... _lastKnownRealMouse:" << _lastKnownRealMouse; + qDebug() << __FUNCTION__ << "() ............. newPosition:" << newPosition; + qDebug() << __FUNCTION__ << "() ....... changeInRealMouse:" << changeInRealMouse; + auto newReticlePosition = _reticlePositionInHMD + toGlm(changeInRealMouse); + _lastKnownRealMouse = newPosition; + + qDebug() << ".... about to call setReticlePosition() newReticlePosition:" << newReticlePosition; + setReticlePosition(newReticlePosition); +} + +glm::vec2 ApplicationCompositor::getReticlePosition() { + if (qApp->isHMDMode()) { + return _reticlePositionInHMD; + } + return toGlm(QCursor::pos()); +} +void ApplicationCompositor::setReticlePosition(glm::vec2 position) { + if (qApp->isHMDMode()) { + _reticlePositionInHMD = glm::clamp(position, vec2(0), vec2(VIRTUAL_SCREEN_SIZE_X, VIRTUAL_SCREEN_SIZE_Y)); + + // in HMD mode we need to fake our mouse moves... + QPoint globalPos(_reticlePositionInHMD.x, _reticlePositionInHMD.y); + QMouseEvent event(QEvent::MouseMove, globalPos, Qt::NoButton, Qt::NoButton, Qt::NoModifier); + + qDebug() << "about to call .... qApp->fakeMouseEvent(&event);"; + qApp->fakeMouseEvent(&event); + + } else { + // NOTE: This is some debugging code we will leave in while debugging various reticle movement strategies, + // remove it after we're done + const float REASONABLE_CHANGE = 50.0f; + glm::vec2 oldPos = toGlm(QCursor::pos()); + auto distance = glm::distance(oldPos, position); + if (distance > REASONABLE_CHANGE) { + qDebug() << "Contrller::ScriptingInterface ---- UNREASONABLE CHANGE! distance:" << distance << " oldPos:" << oldPos << " newPos:" << position; + } + + QCursor::setPos(position.x, position.y); + } +} + // FIXME - this probably is hella buggy and probably doesn't work correctly // we should kill it asap. @@ -460,7 +541,7 @@ void ApplicationCompositor::drawSphereSection(gpu::Batch& batch) { } glm::vec2 ApplicationCompositor::screenToSpherical(const glm::vec2& screenPos) { - auto screenSize = qApp->getCanvasSize(); + glm::uvec2 screenSize { VIRTUAL_SCREEN_SIZE_X, VIRTUAL_SCREEN_SIZE_Y }; // = qApp->getCanvasSize(); glm::vec2 result; result.x = -(screenPos.x / screenSize.x - 0.5f); result.y = (screenPos.y / screenSize.y - 0.5f); @@ -470,11 +551,12 @@ glm::vec2 ApplicationCompositor::screenToSpherical(const glm::vec2& screenPos) { } glm::vec2 ApplicationCompositor::sphericalToScreen(const glm::vec2& sphericalPos) { + glm::uvec2 screenSize { VIRTUAL_SCREEN_SIZE_X, VIRTUAL_SCREEN_SIZE_Y }; // = qApp->getCanvasSize(); glm::vec2 result = sphericalPos; result.x *= -1.0f; result /= MOUSE_RANGE; result += 0.5f; - result *= qApp->getCanvasSize(); + result *= screenSize; return result; } diff --git a/interface/src/ui/ApplicationCompositor.h b/interface/src/ui/ApplicationCompositor.h index fbac59a40c..8d8d7c62d5 100644 --- a/interface/src/ui/ApplicationCompositor.h +++ b/interface/src/ui/ApplicationCompositor.h @@ -10,6 +10,7 @@ #define hifi_ApplicationCompositor_h #include +#include #include #include #include @@ -25,6 +26,10 @@ class PalmData; class RenderArgs; class ReticleInterface; +const int VIRTUAL_SCREEN_SIZE_X = 4096; +const int VIRTUAL_SCREEN_SIZE_Y = 2160; + + const float MAGNIFY_WIDTH = 220.0f; const float MAGNIFY_HEIGHT = 100.0f; const float MAGNIFY_MULT = 2.0f; @@ -88,24 +93,16 @@ public: Q_INVOKABLE float getReticleDepth() { return _reticleDepth; } Q_INVOKABLE void setReticleDepth(float depth) { _reticleDepth = depth; } - Q_INVOKABLE glm::vec2 getReticlePosition() { - return toGlm(QCursor::pos()); - } - Q_INVOKABLE void setReticlePosition(glm::vec2 position) { - // NOTE: This is some debugging code we will leave in while debugging various reticle movement strategies, - // remove it after we're done - const float REASONABLE_CHANGE = 50.0f; - glm::vec2 oldPos = toGlm(QCursor::pos()); - auto distance = glm::distance(oldPos, position); - if (distance > REASONABLE_CHANGE) { - qDebug() << "Contrller::ScriptingInterface ---- UNREASONABLE CHANGE! distance:" << distance << " oldPos:" << oldPos << " newPos:" << position; - } - - QCursor::setPos(position.x, position.y); - } + Q_INVOKABLE glm::vec2 getReticlePosition(); + Q_INVOKABLE void setReticlePosition(glm::vec2 position); ReticleInterface* getReticleInterface() { return _reticleInterface; } + void handleRealMouseMoveEvent(QMouseEvent* event); + void trackRealMouseMoveEvent(QMouseEvent* event); + void handleLeaveEvent(); + QPointF getMouseEventPosition(QMouseEvent* event); + private: void displayOverlayTextureStereo(RenderArgs* renderArgs, float aspectRatio, float fov); @@ -146,6 +143,14 @@ private: bool _reticleVisible { true }; float _reticleDepth { 1.0f }; + // NOTE: when the compositor is running in HMD mode, it will control the reticle position as a custom + // application specific position, when it's in desktop mode, the reticle position will simply move + // the system mouse. + glm::vec2 _reticlePositionInHMD{ 0.0f, 0.0f }; + QPointF _lastKnownRealMouse; + QPoint _lastKnownCursorPos; + bool _ignoreMouseMove { false }; + ReticleInterface* _reticleInterface; }; diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 1967e14d6e..85a4b13b29 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -492,16 +492,16 @@ RayToEntityIntersectionResult EntityTreeRenderer::findRayIntersectionWorker(cons void EntityTreeRenderer::connectSignalsToSlots(EntityScriptingInterface* entityScriptingInterface) { connect(this, &EntityTreeRenderer::mousePressOnEntity, entityScriptingInterface, - [=](const RayToEntityIntersectionResult& intersection, const QMouseEvent* event, unsigned int deviceId){ - entityScriptingInterface->mousePressOnEntity(intersection.entityID, MouseEvent(*event, deviceId)); + [=](const RayToEntityIntersectionResult& intersection, const QMouseEvent* event){ + entityScriptingInterface->mousePressOnEntity(intersection.entityID, MouseEvent(*event)); }); connect(this, &EntityTreeRenderer::mouseMoveOnEntity, entityScriptingInterface, - [=](const RayToEntityIntersectionResult& intersection, const QMouseEvent* event, unsigned int deviceId) { - entityScriptingInterface->mouseMoveOnEntity(intersection.entityID, MouseEvent(*event, deviceId)); + [=](const RayToEntityIntersectionResult& intersection, const QMouseEvent* event) { + entityScriptingInterface->mouseMoveOnEntity(intersection.entityID, MouseEvent(*event)); }); connect(this, &EntityTreeRenderer::mouseReleaseOnEntity, entityScriptingInterface, - [=](const RayToEntityIntersectionResult& intersection, const QMouseEvent* event, unsigned int deviceId) { - entityScriptingInterface->mouseReleaseOnEntity(intersection.entityID, MouseEvent(*event, deviceId)); + [=](const RayToEntityIntersectionResult& intersection, const QMouseEvent* event) { + entityScriptingInterface->mouseReleaseOnEntity(intersection.entityID, MouseEvent(*event)); }); connect(this, &EntityTreeRenderer::clickDownOnEntity, entityScriptingInterface, &EntityScriptingInterface::clickDownOnEntity); @@ -519,7 +519,7 @@ void EntityTreeRenderer::connectSignalsToSlots(EntityScriptingInterface* entityS connect(DependencyManager::get().data(), &SceneScriptingInterface::shouldRenderEntitiesChanged, this, &EntityTreeRenderer::updateEntityRenderStatus, Qt::QueuedConnection); } -void EntityTreeRenderer::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { +void EntityTreeRenderer::mousePressEvent(QMouseEvent* event) { // If we don't have a tree, or we're in the process of shutting down, then don't // process these events. if (!_tree || _shuttingDown) { @@ -540,20 +540,20 @@ void EntityTreeRenderer::mousePressEvent(QMouseEvent* event, unsigned int device } - emit mousePressOnEntity(rayPickResult, event, deviceID); - _entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "mousePressOnEntity", MouseEvent(*event, deviceID)); + emit mousePressOnEntity(rayPickResult, event); + _entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "mousePressOnEntity", MouseEvent(*event)); _currentClickingOnEntityID = rayPickResult.entityID; - emit clickDownOnEntity(_currentClickingOnEntityID, MouseEvent(*event, deviceID)); - _entitiesScriptEngine->callEntityScriptMethod(_currentClickingOnEntityID, "clickDownOnEntity", MouseEvent(*event, deviceID)); + emit clickDownOnEntity(_currentClickingOnEntityID, MouseEvent(*event)); + _entitiesScriptEngine->callEntityScriptMethod(_currentClickingOnEntityID, "clickDownOnEntity", MouseEvent(*event)); } else { - emit mousePressOffEntity(rayPickResult, event, deviceID); + emit mousePressOffEntity(rayPickResult, event); } - _lastMouseEvent = MouseEvent(*event, deviceID); + _lastMouseEvent = MouseEvent(*event); _lastMouseEventValid = true; } -void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) { +void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event) { // If we don't have a tree, or we're in the process of shutting down, then don't // process these events. if (!_tree || _shuttingDown) { @@ -565,24 +565,24 @@ void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event, unsigned int devi RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking); if (rayPickResult.intersects) { //qCDebug(entitiesrenderer) << "mouseReleaseEvent over entity:" << rayPickResult.entityID; - emit mouseReleaseOnEntity(rayPickResult, event, deviceID); - _entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "mouseReleaseOnEntity", MouseEvent(*event, deviceID)); + emit mouseReleaseOnEntity(rayPickResult, event); + _entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "mouseReleaseOnEntity", MouseEvent(*event)); } // Even if we're no longer intersecting with an entity, if we started clicking on it, and now // we're releasing the button, then this is considered a clickOn event if (!_currentClickingOnEntityID.isInvalidID()) { - emit clickReleaseOnEntity(_currentClickingOnEntityID, MouseEvent(*event, deviceID)); - _entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "clickReleaseOnEntity", MouseEvent(*event, deviceID)); + emit clickReleaseOnEntity(_currentClickingOnEntityID, MouseEvent(*event)); + _entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "clickReleaseOnEntity", MouseEvent(*event)); } // makes it the unknown ID, we just released so we can't be clicking on anything _currentClickingOnEntityID = UNKNOWN_ENTITY_ID; - _lastMouseEvent = MouseEvent(*event, deviceID); + _lastMouseEvent = MouseEvent(*event); _lastMouseEventValid = true; } -void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) { +void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) { // If we don't have a tree, or we're in the process of shutting down, then don't // process these events. if (!_tree || _shuttingDown) { @@ -596,28 +596,28 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event, unsigned int deviceI RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::TryLock, precisionPicking); if (rayPickResult.intersects) { - _entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "mouseMoveEvent", MouseEvent(*event, deviceID)); - _entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "mouseMoveOnEntity", MouseEvent(*event, deviceID)); + _entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "mouseMoveEvent", MouseEvent(*event)); + _entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "mouseMoveOnEntity", MouseEvent(*event)); // handle the hover logic... // if we were previously hovering over an entity, and this new entity is not the same as our previous entity // then we need to send the hover leave. if (!_currentHoverOverEntityID.isInvalidID() && rayPickResult.entityID != _currentHoverOverEntityID) { - emit hoverLeaveEntity(_currentHoverOverEntityID, MouseEvent(*event, deviceID)); - _entitiesScriptEngine->callEntityScriptMethod(_currentHoverOverEntityID, "hoverLeaveEntity", MouseEvent(*event, deviceID)); + emit hoverLeaveEntity(_currentHoverOverEntityID, MouseEvent(*event)); + _entitiesScriptEngine->callEntityScriptMethod(_currentHoverOverEntityID, "hoverLeaveEntity", MouseEvent(*event)); } // If the new hover entity does not match the previous hover entity then we are entering the new one // this is true if the _currentHoverOverEntityID is known or unknown if (rayPickResult.entityID != _currentHoverOverEntityID) { - _entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "hoverEnterEntity", MouseEvent(*event, deviceID)); + _entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "hoverEnterEntity", MouseEvent(*event)); } // and finally, no matter what, if we're intersecting an entity then we're definitely hovering over it, and // we should send our hover over event - emit hoverOverEntity(rayPickResult.entityID, MouseEvent(*event, deviceID)); - _entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "hoverOverEntity", MouseEvent(*event, deviceID)); + emit hoverOverEntity(rayPickResult.entityID, MouseEvent(*event)); + _entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "hoverOverEntity", MouseEvent(*event)); // remember what we're hovering over _currentHoverOverEntityID = rayPickResult.entityID; @@ -627,8 +627,8 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event, unsigned int deviceI // if we were previously hovering over an entity, and we're no longer hovering over any entity then we need to // send the hover leave for our previous entity if (!_currentHoverOverEntityID.isInvalidID()) { - emit hoverLeaveEntity(_currentHoverOverEntityID, MouseEvent(*event, deviceID)); - _entitiesScriptEngine->callEntityScriptMethod(_currentHoverOverEntityID, "hoverLeaveEntity", MouseEvent(*event, deviceID)); + emit hoverLeaveEntity(_currentHoverOverEntityID, MouseEvent(*event)); + _entitiesScriptEngine->callEntityScriptMethod(_currentHoverOverEntityID, "hoverLeaveEntity", MouseEvent(*event)); _currentHoverOverEntityID = UNKNOWN_ENTITY_ID; // makes it the unknown ID } } @@ -636,10 +636,10 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event, unsigned int deviceI // Even if we're no longer intersecting with an entity, if we started clicking on an entity and we have // not yet released the hold then this is still considered a holdingClickOnEntity event if (!_currentClickingOnEntityID.isInvalidID()) { - emit holdingClickOnEntity(_currentClickingOnEntityID, MouseEvent(*event, deviceID)); - _entitiesScriptEngine->callEntityScriptMethod(_currentClickingOnEntityID, "holdingClickOnEntity", MouseEvent(*event, deviceID)); + emit holdingClickOnEntity(_currentClickingOnEntityID, MouseEvent(*event)); + _entitiesScriptEngine->callEntityScriptMethod(_currentClickingOnEntityID, "holdingClickOnEntity", MouseEvent(*event)); } - _lastMouseEvent = MouseEvent(*event, deviceID); + _lastMouseEvent = MouseEvent(*event); _lastMouseEventValid = true; } diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index 2a3d688492..f0454b2ecf 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -74,9 +74,9 @@ public: void deleteReleasedModels(); // event handles which may generate entity related events - void mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID); - void mousePressEvent(QMouseEvent* event, unsigned int deviceID); - void mouseMoveEvent(QMouseEvent* event, unsigned int deviceID); + void mouseReleaseEvent(QMouseEvent* event); + void mousePressEvent(QMouseEvent* event); + void mouseMoveEvent(QMouseEvent* event); /// connect our signals to anEntityScriptingInterface for firing of events related clicking, /// hovering over, and entering entities @@ -86,10 +86,10 @@ public: QList& getEntitiesLastInScene() { return _entityIDsLastInScene; } signals: - void mousePressOnEntity(const RayToEntityIntersectionResult& intersection, const QMouseEvent* event, unsigned int deviceId); - void mousePressOffEntity(const RayToEntityIntersectionResult& intersection, const QMouseEvent* event, unsigned int deviceId); - void mouseMoveOnEntity(const RayToEntityIntersectionResult& intersection, const QMouseEvent* event, unsigned int deviceId); - void mouseReleaseOnEntity(const RayToEntityIntersectionResult& intersection, const QMouseEvent* event, unsigned int deviceId); + void mousePressOnEntity(const RayToEntityIntersectionResult& intersection, const QMouseEvent* event); + void mousePressOffEntity(const RayToEntityIntersectionResult& intersection, const QMouseEvent* event); + void mouseMoveOnEntity(const RayToEntityIntersectionResult& intersection, const QMouseEvent* event); + void mouseReleaseOnEntity(const RayToEntityIntersectionResult& intersection, const QMouseEvent* event); void clickDownOnEntity(const EntityItemID& entityItemID, const MouseEvent& event); void holdingClickOnEntity(const EntityItemID& entityItemID, const MouseEvent& event); diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index ce89197069..8140dd3312 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -85,7 +85,7 @@ void RenderableWebEntityItem::render(RenderArgs* args) { _texture = textureId; }); - auto forwardMouseEvent = [=](const RayToEntityIntersectionResult& intersection, const QMouseEvent* event, unsigned int deviceId) { + auto forwardMouseEvent = [=](const RayToEntityIntersectionResult& intersection, const QMouseEvent* event) { // Ignore mouse interaction if we're locked if (this->getLocked()) { return; diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp index c3d2f7c51c..0bf398cdec 100755 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp @@ -57,7 +57,7 @@ void KeyboardMouseDevice::keyReleaseEvent(QKeyEvent* event) { _inputDevice->_buttonPressedMap.erase(input.getChannel()); } -void KeyboardMouseDevice::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { +void KeyboardMouseDevice::mousePressEvent(QMouseEvent* event) { auto input = _inputDevice->makeInput((Qt::MouseButton) event->button()); auto result = _inputDevice->_buttonPressedMap.insert(input.getChannel()); if (!result.second) { @@ -70,7 +70,7 @@ void KeyboardMouseDevice::mousePressEvent(QMouseEvent* event, unsigned int devic eraseMouseClicked(); } -void KeyboardMouseDevice::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) { +void KeyboardMouseDevice::mouseReleaseEvent(QMouseEvent* event) { auto input = _inputDevice->makeInput((Qt::MouseButton) event->button()); _inputDevice->_buttonPressedMap.erase(input.getChannel()); @@ -89,7 +89,7 @@ void KeyboardMouseDevice::eraseMouseClicked() { _inputDevice->_buttonPressedMap.erase(_inputDevice->makeInput(Qt::RightButton, true).getChannel()); } -void KeyboardMouseDevice::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) { +void KeyboardMouseDevice::mouseMoveEvent(QMouseEvent* event) { QPoint currentPos = event->pos(); QPoint currentMove = currentPos - _lastCursor; diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h index 55ca9a1704..67d9ccb1b2 100644 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h @@ -75,9 +75,9 @@ public: void keyPressEvent(QKeyEvent* event); void keyReleaseEvent(QKeyEvent* event); - void mouseMoveEvent(QMouseEvent* event, unsigned int deviceID = 0); - void mousePressEvent(QMouseEvent* event, unsigned int deviceID = 0); - void mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID = 0); + void mouseMoveEvent(QMouseEvent* event); + void mousePressEvent(QMouseEvent* event); + void mouseReleaseEvent(QMouseEvent* event); void eraseMouseClicked(); void touchBeginEvent(const QTouchEvent* event); diff --git a/libraries/script-engine/src/MouseEvent.cpp b/libraries/script-engine/src/MouseEvent.cpp index 34b3eb693e..31bca8054d 100644 --- a/libraries/script-engine/src/MouseEvent.cpp +++ b/libraries/script-engine/src/MouseEvent.cpp @@ -29,10 +29,9 @@ MouseEvent::MouseEvent() : } -MouseEvent::MouseEvent(const QMouseEvent& event, const unsigned int deviceID) : +MouseEvent::MouseEvent(const QMouseEvent& event) : x(event.x()), y(event.y()), - deviceID(deviceID), isLeftButton(event.buttons().testFlag(Qt::LeftButton)), isRightButton(event.buttons().testFlag(Qt::RightButton)), isMiddleButton(event.buttons().testFlag(Qt::MiddleButton)), @@ -66,7 +65,6 @@ QScriptValue MouseEvent::toScriptValue(QScriptEngine* engine, const MouseEvent& obj.setProperty("x", event.x); obj.setProperty("y", event.y); obj.setProperty("button", event.button); - obj.setProperty("deviceID", event.deviceID); obj.setProperty("isLeftButton", event.isLeftButton); obj.setProperty("isRightButton", event.isRightButton); obj.setProperty("isMiddleButton", event.isMiddleButton); diff --git a/libraries/script-engine/src/MouseEvent.h b/libraries/script-engine/src/MouseEvent.h index 1936e6b58e..0fbc688e5f 100644 --- a/libraries/script-engine/src/MouseEvent.h +++ b/libraries/script-engine/src/MouseEvent.h @@ -17,7 +17,7 @@ class MouseEvent { public: MouseEvent(); - MouseEvent(const QMouseEvent& event, const unsigned int deviceID = 0); + MouseEvent(const QMouseEvent& event); static QScriptValue toScriptValue(QScriptEngine* engine, const MouseEvent& event); static void fromScriptValue(const QScriptValue& object, MouseEvent& event); @@ -26,7 +26,6 @@ public: int x; int y; - unsigned int deviceID; QString button; bool isLeftButton; bool isRightButton; From 279519b6d56669ae2f1260d16a9245a08d9e59ba Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Thu, 18 Feb 2016 08:44:22 -0800 Subject: [PATCH 10/72] hmd mouse check point --- interface/src/Application.cpp | 12 +++++---- interface/src/ui/ApplicationCompositor.cpp | 27 +++++++++++---------- interface/src/ui/ApplicationCompositor.h | 6 ++--- libraries/gl/src/gl/OffscreenQmlSurface.cpp | 2 ++ 4 files changed, 26 insertions(+), 21 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9235f20a89..7a0a3f03be 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1266,6 +1266,7 @@ void Application::initializeUi() { QPointF result = pt; auto displayPlugin = getActiveDisplayPlugin(); if (displayPlugin->isHmd()) { + _compositor.handleRealMouseMoveEvent(false); auto fakeScreen = _compositor.getReticlePosition(); auto resultVec = _compositor.screenToOverlay(fakeScreen); // toGlm(pt)); result = QPointF(resultVec.x, resultVec.y); @@ -2209,12 +2210,13 @@ void Application::mouseMoveEvent(QMouseEvent* event) { // if this is a real mouse event, and we're in HMD mode, then we should use it to move the // compositor reticle - if (!_fakedMouseEvent && isHMDMode()) { - _compositor.handleRealMouseMoveEvent(event); - return; // bail - } if (!_fakedMouseEvent) { - _compositor.trackRealMouseMoveEvent(event); // FIXME - super janky + if (isHMDMode()) { + _compositor.handleRealMouseMoveEvent(); + return; // bail + } else { + _compositor.trackRealMouseMoveEvent(); // FIXME - super janky + } } auto offscreenUi = DependencyManager::get(); diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 806435a6c2..1f3b0ee1f4 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -321,14 +321,14 @@ void ApplicationCompositor::handleLeaveEvent() { } } -void ApplicationCompositor::trackRealMouseMoveEvent(QMouseEvent* event) { - qDebug() << __FUNCTION__ << "() BEFORE _lastKnownRealMouse:" << _lastKnownRealMouse; +void ApplicationCompositor::trackRealMouseMoveEvent() { + qDebug() << __FUNCTION__ << "(event) BEFORE _lastKnownRealMouse:" << _lastKnownRealMouse; _lastKnownRealMouse = QCursor::pos(); - qDebug() << __FUNCTION__ << "() AFTER _lastKnownRealMouse:" << _lastKnownRealMouse; + qDebug() << __FUNCTION__ << "(event) AFTER _lastKnownRealMouse:" << _lastKnownRealMouse; } -void ApplicationCompositor::handleRealMouseMoveEvent(QMouseEvent* event) { - qDebug() << __FUNCTION__ << "() event:" << event; +void ApplicationCompositor::handleRealMouseMoveEvent(bool sendFakeEvent) { + qDebug() << __FUNCTION__ << "()"; if (_ignoreMouseMove) { qDebug() << __FUNCTION__ << "() IGNORE MOUSE MOVE!!!"; _ignoreMouseMove = false; @@ -347,7 +347,7 @@ void ApplicationCompositor::handleRealMouseMoveEvent(QMouseEvent* event) { _lastKnownRealMouse = newPosition; qDebug() << ".... about to call setReticlePosition() newReticlePosition:" << newReticlePosition; - setReticlePosition(newReticlePosition); + setReticlePosition(newReticlePosition, sendFakeEvent); } glm::vec2 ApplicationCompositor::getReticlePosition() { @@ -356,17 +356,18 @@ glm::vec2 ApplicationCompositor::getReticlePosition() { } return toGlm(QCursor::pos()); } -void ApplicationCompositor::setReticlePosition(glm::vec2 position) { +void ApplicationCompositor::setReticlePosition(glm::vec2 position, bool sendFakeEvent) { if (qApp->isHMDMode()) { _reticlePositionInHMD = glm::clamp(position, vec2(0), vec2(VIRTUAL_SCREEN_SIZE_X, VIRTUAL_SCREEN_SIZE_Y)); - // in HMD mode we need to fake our mouse moves... - QPoint globalPos(_reticlePositionInHMD.x, _reticlePositionInHMD.y); - QMouseEvent event(QEvent::MouseMove, globalPos, Qt::NoButton, Qt::NoButton, Qt::NoModifier); - - qDebug() << "about to call .... qApp->fakeMouseEvent(&event);"; - qApp->fakeMouseEvent(&event); + if (sendFakeEvent) { + // in HMD mode we need to fake our mouse moves... + QPoint globalPos(_reticlePositionInHMD.x, _reticlePositionInHMD.y); + QMouseEvent event(QEvent::MouseMove, globalPos, Qt::NoButton, Qt::NoButton, Qt::NoModifier); + qDebug() << "about to call .... qApp->fakeMouseEvent(&event);"; + qApp->fakeMouseEvent(&event); + } } else { // NOTE: This is some debugging code we will leave in while debugging various reticle movement strategies, // remove it after we're done diff --git a/interface/src/ui/ApplicationCompositor.h b/interface/src/ui/ApplicationCompositor.h index 8d8d7c62d5..dda367a023 100644 --- a/interface/src/ui/ApplicationCompositor.h +++ b/interface/src/ui/ApplicationCompositor.h @@ -94,12 +94,12 @@ public: Q_INVOKABLE void setReticleDepth(float depth) { _reticleDepth = depth; } Q_INVOKABLE glm::vec2 getReticlePosition(); - Q_INVOKABLE void setReticlePosition(glm::vec2 position); + Q_INVOKABLE void setReticlePosition(glm::vec2 position, bool sendFakeEvent = true); ReticleInterface* getReticleInterface() { return _reticleInterface; } - void handleRealMouseMoveEvent(QMouseEvent* event); - void trackRealMouseMoveEvent(QMouseEvent* event); + void handleRealMouseMoveEvent(bool sendFakeEvent = true); + void trackRealMouseMoveEvent(); void handleLeaveEvent(); QPointF getMouseEventPosition(QMouseEvent* event); diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index 42eea08057..ad45cb131b 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -573,8 +573,10 @@ bool OffscreenQmlSurface::eventFilter(QObject* originalDestination, QEvent* even case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseMove: { + //qDebug() << __FUNCTION__ << "event:" << event; QMouseEvent* mouseEvent = static_cast(event); QPointF transformedPos = mapToVirtualScreen(mouseEvent->localPos(), originalDestination); + qDebug() << __FUNCTION__ << "transformedPos:" << transformedPos; QMouseEvent mappedEvent(mouseEvent->type(), transformedPos, mouseEvent->screenPos(), mouseEvent->button(), From e6662edcb40ce571c21a9d4c62cdb32910b00070 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Thu, 18 Feb 2016 08:57:06 -0800 Subject: [PATCH 11/72] revert step size change --- examples/html/entityProperties.html | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index b7240d43f7..1688e3cb7c 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -1165,9 +1165,9 @@
Position
-
X
-
Y
-
Z
+
X
+
Y
+
Z
@@ -1201,9 +1201,9 @@
Dimensions
-
X
-
Y
-
Z
+
X
+
Y
+
Z
@@ -1253,9 +1253,9 @@
Rotation
-
Pitch
-
Yaw
-
Roll
+
Pitch
+
Yaw
+
Roll
From acaa824cb507f6375c5f729a362f7a5607b7273d Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Thu, 18 Feb 2016 09:00:39 -0800 Subject: [PATCH 12/72] but only position --- examples/html/entityProperties.html | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index 1688e3cb7c..5ddddfbfea 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -1201,9 +1201,9 @@
Dimensions
-
X
-
Y
-
Z
+
X
+
Y
+
Z
@@ -1253,9 +1253,9 @@
Rotation
-
Pitch
-
Yaw
-
Roll
+
Pitch
+
Yaw
+
Roll
From c4fc3e4057f199028a28d00cf3ec67fac26d5f8f Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Thu, 18 Feb 2016 10:07:37 -0800 Subject: [PATCH 13/72] more work on dragging in hmd --- interface/src/Application.cpp | 14 +++++++------- interface/src/ui/ApplicationCompositor.cpp | 20 +++++--------------- libraries/gl/src/gl/OffscreenQmlSurface.cpp | 2 +- 3 files changed, 13 insertions(+), 23 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7a0a3f03be..b7937ef69c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1743,7 +1743,7 @@ bool Application::event(QEvent* event) { switch (event->type()) { case QEvent::MouseMove: - qDebug() << __FUNCTION__ << "(QEvent::MouseMove)... line:" << __LINE__; + //qDebug() << __FUNCTION__ << "(QEvent::MouseMove)... line:" << __LINE__; mouseMoveEvent((QMouseEvent*)event); return true; case QEvent::MouseButtonPress: @@ -1781,7 +1781,7 @@ bool Application::event(QEvent* event) { dropEvent(static_cast(event)); return true; case QEvent::Leave: - qDebug() << __FUNCTION__ << "().... QEvent::Leave"; + //qDebug() << __FUNCTION__ << "().... QEvent::Leave"; break; // fall through default: break; @@ -1813,7 +1813,7 @@ bool Application::event(QEvent* event) { bool Application::eventFilter(QObject* object, QEvent* event) { if (event->type() == QEvent::Leave) { - qDebug() << __FUNCTION__ << "().... QEvent::Leave"; + //qDebug() << __FUNCTION__ << "().... QEvent::Leave"; _compositor.handleLeaveEvent(); } @@ -2204,7 +2204,7 @@ void Application::mouseMoveEvent(QMouseEvent* event) { if (_aboutToQuit) { return; } - qDebug() << __FUNCTION__ << "line:" << __LINE__ << "event:" << event << "_fakedMouseEvent:" << _fakedMouseEvent; + //qDebug() << __FUNCTION__ << "line:" << __LINE__ << "event:" << event << "_fakedMouseEvent:" << _fakedMouseEvent; maybeToggleMenuVisible(event); @@ -2261,13 +2261,13 @@ void Application::mousePressEvent(QMouseEvent* event) { // keyboard shortcuts not to be swallowed by them. In particular, WebEngineViews // will consume all keyboard events. offscreenUi->unfocusWindows(); - qDebug() << __FUNCTION__ << "event:" << event; + //qDebug() << __FUNCTION__ << "event:" << event; auto eventPosition = _compositor.getMouseEventPosition(event); QPointF transformedPos = offscreenUi->mapToVirtualScreen(eventPosition, _glWidget); - qDebug() << __FUNCTION__ << " eventPosition:" << eventPosition; - qDebug() << __FUNCTION__ << "transformedPos:" << transformedPos; + //qDebug() << __FUNCTION__ << " eventPosition:" << eventPosition; + //qDebug() << __FUNCTION__ << "transformedPos:" << transformedPos; QMouseEvent mappedEvent(event->type(), transformedPos, diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 1f3b0ee1f4..938cd58084 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -313,7 +313,6 @@ QPointF ApplicationCompositor::getMouseEventPosition(QMouseEvent* event) { void ApplicationCompositor::handleLeaveEvent() { if (qApp->isHMDMode()) { auto applicationGeometry = qApp->getApplicationGeometry(); - qDebug() << "SENDING mouse back to center:" << applicationGeometry.center(); _ignoreMouseMove = true; auto sendToPos = applicationGeometry.center(); QCursor::setPos(sendToPos); @@ -322,31 +321,19 @@ void ApplicationCompositor::handleLeaveEvent() { } void ApplicationCompositor::trackRealMouseMoveEvent() { - qDebug() << __FUNCTION__ << "(event) BEFORE _lastKnownRealMouse:" << _lastKnownRealMouse; _lastKnownRealMouse = QCursor::pos(); - qDebug() << __FUNCTION__ << "(event) AFTER _lastKnownRealMouse:" << _lastKnownRealMouse; } void ApplicationCompositor::handleRealMouseMoveEvent(bool sendFakeEvent) { - qDebug() << __FUNCTION__ << "()"; if (_ignoreMouseMove) { - qDebug() << __FUNCTION__ << "() IGNORE MOUSE MOVE!!!"; _ignoreMouseMove = false; return; } - auto applicationGeometry = qApp->getApplicationGeometry(); - qDebug() << ".... applicationGeometry:" << applicationGeometry; - auto newPosition = QCursor::pos(); auto changeInRealMouse = newPosition - _lastKnownRealMouse; - qDebug() << __FUNCTION__ << "() ..... _lastKnownRealMouse:" << _lastKnownRealMouse; - qDebug() << __FUNCTION__ << "() ............. newPosition:" << newPosition; - qDebug() << __FUNCTION__ << "() ....... changeInRealMouse:" << changeInRealMouse; auto newReticlePosition = _reticlePositionInHMD + toGlm(changeInRealMouse); _lastKnownRealMouse = newPosition; - - qDebug() << ".... about to call setReticlePosition() newReticlePosition:" << newReticlePosition; setReticlePosition(newReticlePosition, sendFakeEvent); } @@ -363,9 +350,12 @@ void ApplicationCompositor::setReticlePosition(glm::vec2 position, bool sendFake if (sendFakeEvent) { // in HMD mode we need to fake our mouse moves... QPoint globalPos(_reticlePositionInHMD.x, _reticlePositionInHMD.y); - QMouseEvent event(QEvent::MouseMove, globalPos, Qt::NoButton, Qt::NoButton, Qt::NoModifier); + auto button = Qt::NoButton; + auto buttons = QApplication::mouseButtons(); + auto modifiers = QApplication::keyboardModifiers(); + QMouseEvent event(QEvent::MouseMove, globalPos, button, buttons, modifiers); - qDebug() << "about to call .... qApp->fakeMouseEvent(&event);"; + //qDebug() << "about to call .... qApp->fakeMouseEvent(&event);"; qApp->fakeMouseEvent(&event); } } else { diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index ad45cb131b..ea3fb63d66 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -576,7 +576,7 @@ bool OffscreenQmlSurface::eventFilter(QObject* originalDestination, QEvent* even //qDebug() << __FUNCTION__ << "event:" << event; QMouseEvent* mouseEvent = static_cast(event); QPointF transformedPos = mapToVirtualScreen(mouseEvent->localPos(), originalDestination); - qDebug() << __FUNCTION__ << "transformedPos:" << transformedPos; + //qDebug() << __FUNCTION__ << "transformedPos:" << transformedPos; QMouseEvent mappedEvent(mouseEvent->type(), transformedPos, mouseEvent->screenPos(), mouseEvent->button(), From 613b60658ec716f772bc6163cec58e75738e9518 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 18 Feb 2016 10:24:36 -0800 Subject: [PATCH 14/72] Rig: prevent normalization of a zero vector --- libraries/animation/src/Rig.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 718ae9bb79..3952dc5b40 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1083,6 +1083,7 @@ void Rig::updateFromHandParameters(const HandParameters& params, float dt) { const float HAND_RADIUS = 0.05f; const float BODY_RADIUS = params.bodyCapsuleRadius; + const float MIN_LENGTH = 1.0e-4f; // project the hips onto the xz plane. auto hipsTrans = _internalPoseSet._absolutePoses[_animSkeleton->nameToJointIndex("Hips")].trans; @@ -1092,13 +1093,14 @@ void Rig::updateFromHandParameters(const HandParameters& params, float dt) { // project the hand position onto the xz plane. glm::vec2 handCircleCenter(params.leftPosition.x, params.leftPosition.z); - auto d = handCircleCenter - bodyCircleCenter; // check for 2d overlap of the hand and body circles. - float penetrationDistance = HAND_RADIUS + BODY_RADIUS - glm::length(d); - if (penetrationDistance > 0) { + auto circleToCircle = handCircleCenter - bodyCircleCenter; + const float circleToCircleLength = glm::length(circleToCircle); + const float penetrationDistance = HAND_RADIUS + BODY_RADIUS - circleToCircleLength; + if (penetrationDistance > 0.0f && circleToCircleLength > MIN_LENGTH) { // push the hands out of the body - handCircleCenter += penetrationDistance * glm::normalize(d); + handCircleCenter += penetrationDistance * glm::normalize(circleToCircle); } glm::vec3 handPosition(handCircleCenter.x, params.leftPosition.y, handCircleCenter.y); @@ -1115,13 +1117,14 @@ void Rig::updateFromHandParameters(const HandParameters& params, float dt) { // project the hand position onto the xz plane. glm::vec2 handCircleCenter(params.rightPosition.x, params.rightPosition.z); - auto d = handCircleCenter - bodyCircleCenter; // check for 2d overlap of the hand and body circles. - float penetrationDistance = HAND_RADIUS + BODY_RADIUS - glm::length(d); - if (penetrationDistance > 0) { + auto circleToCircle = handCircleCenter - bodyCircleCenter; + const float circleToCircleLength = glm::length(circleToCircle); + const float penetrationDistance = HAND_RADIUS + BODY_RADIUS - circleToCircleLength; + if (penetrationDistance > 0.0f && circleToCircleLength > MIN_LENGTH) { // push the hands out of the body - handCircleCenter += penetrationDistance * glm::normalize(d); + handCircleCenter += penetrationDistance * glm::normalize(circleToCircle); } glm::vec3 handPosition(handCircleCenter.x, params.rightPosition.y, handCircleCenter.y); From eabeb9807671d3fd1cd3040adfdae3af0e8ddcc9 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 18 Feb 2016 11:50:26 -0800 Subject: [PATCH 15/72] injector load --- examples/audioExamples/injectorLoadTest.js | 55 ++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 examples/audioExamples/injectorLoadTest.js diff --git a/examples/audioExamples/injectorLoadTest.js b/examples/audioExamples/injectorLoadTest.js new file mode 100644 index 0000000000..e25e964f3c --- /dev/null +++ b/examples/audioExamples/injectorLoadTest.js @@ -0,0 +1,55 @@ +// +// injectorLoadTest.js +// audio +// +// Created by Eric Levin 2/1/2016 +// Copyright 2016 High Fidelity, Inc. + +// This script tests what happens when many audio injectors are created and played +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + + +Script.include("../libraries/utils.js"); + +// A green box represents an injector that is playing + +var basePosition = { + x: 0, + y: 0, + z: 0 +}; + +var soundBoxes = []; + +var testSound = SoundCache.getSound("https://s3-us-west-1.amazonaws.com/hifi-content/eric/Sounds/dove.wav"); + +var numSounds = 45; +for (var i = 0; i < numSounds; i++) { + playSound(); +} + +function playSound() { + var position = Vec3.sum(basePosition, {x: randFloat(-.1, .1), y: randFloat(-1, 1), z: randFloat(-3, -.1)}); + var injector = Audio.playSound(testSound, { + position: position, + volume: 0.3 + }); + + var soundBox = Entities.addEntity({ + type: "Box", + color: {red: 200, green: 10, blue: 200}, + dimensions: {x: 0.1, y: 0.1, z: 0.1}, + position: position + }); + + soundBoxes.push(soundBox); +} + +function cleanup() { + soundBoxes.forEach( function(soundBox) { + Entities.deleteEntity(soundBox); + }); +} + +Script.scriptEnding.connect(cleanup); \ No newline at end of file From 1d9b3fadaf19e1213616c2c166e0865cf1a37f06 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 18 Feb 2016 12:00:24 -0800 Subject: [PATCH 16/72] more logging --- examples/audioExamples/injectorLoadTest.js | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/examples/audioExamples/injectorLoadTest.js b/examples/audioExamples/injectorLoadTest.js index e25e964f3c..d394e3a49b 100644 --- a/examples/audioExamples/injectorLoadTest.js +++ b/examples/audioExamples/injectorLoadTest.js @@ -24,11 +24,26 @@ var soundBoxes = []; var testSound = SoundCache.getSound("https://s3-us-west-1.amazonaws.com/hifi-content/eric/Sounds/dove.wav"); -var numSounds = 45; -for (var i = 0; i < numSounds; i++) { - playSound(); +if(!testSound.downloaded) { + + print("EBL SOUND IS NOT READY YET") + testSound.ready.connect(function() { + playSounds(); + }); +} else { + // otherwise play sounds right away + playSounds(); } +function playSounds() { + print("EBL PLAY SOUNDS!") + var numSounds = 45; + for (var i = 0; i < numSounds; i++) { + playSound(); + } +} + + function playSound() { var position = Vec3.sum(basePosition, {x: randFloat(-.1, .1), y: randFloat(-1, 1), z: randFloat(-3, -.1)}); var injector = Audio.playSound(testSound, { From 935af6d2cc3f7332bdd6ee75cc80649c32b15817 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Thu, 18 Feb 2016 12:01:03 -0800 Subject: [PATCH 17/72] clean up debug logs --- interface/src/Application.cpp | 13 ------------- interface/src/ui/ApplicationCompositor.cpp | 3 --- 2 files changed, 16 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 63b43e741e..6e9e42ff66 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -812,11 +812,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : auto reticlePosition = _compositor.getReticlePosition(); offscreenUi->toggleMenu(_glWidget->mapFromGlobal(QPoint(reticlePosition.x, reticlePosition.y))); } else if (action == controller::toInt(controller::Action::RETICLE_X)) { - qDebug() << "Action::RETICLE_X..."; auto oldPos = _compositor.getReticlePosition(); _compositor.setReticlePosition({ oldPos.x + state, oldPos.y }); } else if (action == controller::toInt(controller::Action::RETICLE_Y)) { - qDebug() << "Action::RETICLE_Y..."; auto oldPos = _compositor.getReticlePosition(); _compositor.setReticlePosition({ oldPos.x, oldPos.y + state }); } @@ -1743,7 +1741,6 @@ bool Application::event(QEvent* event) { switch (event->type()) { case QEvent::MouseMove: - //qDebug() << __FUNCTION__ << "(QEvent::MouseMove)... line:" << __LINE__; mouseMoveEvent((QMouseEvent*)event); return true; case QEvent::MouseButtonPress: @@ -1780,9 +1777,6 @@ bool Application::event(QEvent* event) { case QEvent::Drop: dropEvent(static_cast(event)); return true; - case QEvent::Leave: - //qDebug() << __FUNCTION__ << "().... QEvent::Leave"; - break; // fall through default: break; } @@ -1813,7 +1807,6 @@ bool Application::event(QEvent* event) { bool Application::eventFilter(QObject* object, QEvent* event) { if (event->type() == QEvent::Leave) { - //qDebug() << __FUNCTION__ << "().... QEvent::Leave"; _compositor.handleLeaveEvent(); } @@ -2204,7 +2197,6 @@ void Application::mouseMoveEvent(QMouseEvent* event) { if (_aboutToQuit) { return; } - //qDebug() << __FUNCTION__ << "line:" << __LINE__ << "event:" << event << "_fakedMouseEvent:" << _fakedMouseEvent; maybeToggleMenuVisible(event); @@ -2261,14 +2253,9 @@ void Application::mousePressEvent(QMouseEvent* event) { // keyboard shortcuts not to be swallowed by them. In particular, WebEngineViews // will consume all keyboard events. offscreenUi->unfocusWindows(); - //qDebug() << __FUNCTION__ << "event:" << event; auto eventPosition = _compositor.getMouseEventPosition(event); QPointF transformedPos = offscreenUi->mapToVirtualScreen(eventPosition, _glWidget); - - //qDebug() << __FUNCTION__ << " eventPosition:" << eventPosition; - //qDebug() << __FUNCTION__ << "transformedPos:" << transformedPos; - QMouseEvent mappedEvent(event->type(), transformedPos, event->screenPos(), event->button(), diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 938cd58084..1ae9708783 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -290,7 +290,6 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int _modelTransform.getMatrix(overlayXfm); auto reticlePosition = getReticlePosition(); - //qDebug() << "reticlePosition:" << reticlePosition; // FIXME - remove this debugging glm::vec2 projection = screenToSpherical(reticlePosition); float cursorDepth = getReticleDepth(); mat4 pointerXfm = glm::scale(mat4(), vec3(cursorDepth)) * glm::mat4_cast(quat(vec3(-projection.y, projection.x, 0.0f))) * glm::translate(mat4(), vec3(0, 0, -1)); @@ -354,8 +353,6 @@ void ApplicationCompositor::setReticlePosition(glm::vec2 position, bool sendFake auto buttons = QApplication::mouseButtons(); auto modifiers = QApplication::keyboardModifiers(); QMouseEvent event(QEvent::MouseMove, globalPos, button, buttons, modifiers); - - //qDebug() << "about to call .... qApp->fakeMouseEvent(&event);"; qApp->fakeMouseEvent(&event); } } else { From ec1c7925c04c55c657e8f2ff603e871d0775172d Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 18 Feb 2016 12:02:22 -0800 Subject: [PATCH 18/72] updated logging --- examples/audioExamples/injectorLoadTest.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/audioExamples/injectorLoadTest.js b/examples/audioExamples/injectorLoadTest.js index d394e3a49b..35e3e07868 100644 --- a/examples/audioExamples/injectorLoadTest.js +++ b/examples/audioExamples/injectorLoadTest.js @@ -26,7 +26,7 @@ var testSound = SoundCache.getSound("https://s3-us-west-1.amazonaws.com/hifi-con if(!testSound.downloaded) { - print("EBL SOUND IS NOT READY YET") + print("SOUND IS NOT READY YET") testSound.ready.connect(function() { playSounds(); }); @@ -36,7 +36,7 @@ if(!testSound.downloaded) { } function playSounds() { - print("EBL PLAY SOUNDS!") + print("PLAY SOUNDS!") var numSounds = 45; for (var i = 0; i < numSounds; i++) { playSound(); From 843039f7413a5a211573e26a8cf5ffb2928e9ce3 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Thu, 18 Feb 2016 12:04:38 -0800 Subject: [PATCH 19/72] fix mac warnings --- interface/src/ui/ApplicationCompositor.cpp | 1 - interface/src/ui/ApplicationCompositor.h | 2 +- interface/src/ui/overlays/Text3DOverlay.cpp | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 1ae9708783..4b5d323aeb 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -328,7 +328,6 @@ void ApplicationCompositor::handleRealMouseMoveEvent(bool sendFakeEvent) { _ignoreMouseMove = false; return; } - auto applicationGeometry = qApp->getApplicationGeometry(); auto newPosition = QCursor::pos(); auto changeInRealMouse = newPosition - _lastKnownRealMouse; auto newReticlePosition = _reticlePositionInHMD + toGlm(changeInRealMouse); diff --git a/interface/src/ui/ApplicationCompositor.h b/interface/src/ui/ApplicationCompositor.h index dda367a023..869e97ec60 100644 --- a/interface/src/ui/ApplicationCompositor.h +++ b/interface/src/ui/ApplicationCompositor.h @@ -162,7 +162,7 @@ class ReticleInterface : public QObject { Q_PROPERTY(bool visible READ getVisible WRITE setVisible) Q_PROPERTY(float depth READ getDepth WRITE setDepth) public: - ReticleInterface(ApplicationCompositor* outer) : _compositor(outer), QObject(outer) { } + ReticleInterface(ApplicationCompositor* outer) : QObject(outer), _compositor(outer) {} Q_INVOKABLE bool getVisible() { return _compositor->getReticleVisible(); } Q_INVOKABLE void setVisible(bool visible) { _compositor->setReticleVisible(visible); } diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index 6c8c118df9..60cf6bcd4d 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -17,7 +17,6 @@ #include #include -const float DEFAULT_MARGIN = 0.1f; const int FIXED_FONT_POINT_SIZE = 40; const int FIXED_FONT_SCALING_RATIO = FIXED_FONT_POINT_SIZE * 80.0f; // this is a ratio determined through experimentation const float LINE_SCALE_RATIO = 1.2f; From efbb5ec9670a3955912c10de1d1abd4d6c0899f0 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 18 Feb 2016 12:14:30 -0800 Subject: [PATCH 20/72] updated test --- examples/audioExamples/injectorLoadTest.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/examples/audioExamples/injectorLoadTest.js b/examples/audioExamples/injectorLoadTest.js index 35e3e07868..3842678590 100644 --- a/examples/audioExamples/injectorLoadTest.js +++ b/examples/audioExamples/injectorLoadTest.js @@ -12,6 +12,9 @@ Script.include("../libraries/utils.js"); + +var numSoundsToPlayPerBatch = 1; +var timeBetweenBatch = 100; // A green box represents an injector that is playing var basePosition = { @@ -23,6 +26,7 @@ var basePosition = { var soundBoxes = []; var testSound = SoundCache.getSound("https://s3-us-west-1.amazonaws.com/hifi-content/eric/Sounds/dove.wav"); +var totalInjectors = 0; if(!testSound.downloaded) { @@ -37,10 +41,14 @@ if(!testSound.downloaded) { function playSounds() { print("PLAY SOUNDS!") - var numSounds = 45; - for (var i = 0; i < numSounds; i++) { + for (var i = 0; i < numSoundsToPlayPerBatch; i++) { playSound(); - } + } + print("EBL Total Number of Injectors: " + totalInjectors); + + Script.setTimeout(function() { + playSounds(); + }, timeBetweenBatch); } @@ -48,8 +56,9 @@ function playSound() { var position = Vec3.sum(basePosition, {x: randFloat(-.1, .1), y: randFloat(-1, 1), z: randFloat(-3, -.1)}); var injector = Audio.playSound(testSound, { position: position, - volume: 0.3 + volume: 0.1 }); + totalInjectors++; var soundBox = Entities.addEntity({ type: "Box", From adcadedc65cb329746c2f737d56b493029191bde Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Thu, 18 Feb 2016 14:40:55 -0800 Subject: [PATCH 21/72] slight rework of handleRealMouseMoveEvent --- interface/src/Application.cpp | 6 ++--- interface/src/ui/ApplicationCompositor.cpp | 26 +++++++++++++--------- interface/src/ui/ApplicationCompositor.h | 4 ++-- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6e9e42ff66..dd7c524cd5 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2203,11 +2203,9 @@ void Application::mouseMoveEvent(QMouseEvent* event) { // if this is a real mouse event, and we're in HMD mode, then we should use it to move the // compositor reticle if (!_fakedMouseEvent) { - if (isHMDMode()) { - _compositor.handleRealMouseMoveEvent(); + // handleRealMouseMoveEvent() will return true, if we shouldn't process the event further + if (_compositor.handleRealMouseMoveEvent()) { return; // bail - } else { - _compositor.trackRealMouseMoveEvent(); // FIXME - super janky } } diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 4b5d323aeb..4588a24ac0 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -319,20 +319,26 @@ void ApplicationCompositor::handleLeaveEvent() { } } -void ApplicationCompositor::trackRealMouseMoveEvent() { - _lastKnownRealMouse = QCursor::pos(); -} +bool ApplicationCompositor::handleRealMouseMoveEvent(bool sendFakeEvent) { -void ApplicationCompositor::handleRealMouseMoveEvent(bool sendFakeEvent) { + // If the mouse move came from a capture mouse related move, we completely ignore it. if (_ignoreMouseMove) { _ignoreMouseMove = false; - return; + return true; // swallow the event } - auto newPosition = QCursor::pos(); - auto changeInRealMouse = newPosition - _lastKnownRealMouse; - auto newReticlePosition = _reticlePositionInHMD + toGlm(changeInRealMouse); - _lastKnownRealMouse = newPosition; - setReticlePosition(newReticlePosition, sendFakeEvent); + + // If we're in HMD mode + if (qApp->isHMDMode()) { + auto newPosition = QCursor::pos(); + auto changeInRealMouse = newPosition - _lastKnownRealMouse; + auto newReticlePosition = _reticlePositionInHMD + toGlm(changeInRealMouse); + _lastKnownRealMouse = newPosition; + setReticlePosition(newReticlePosition, sendFakeEvent); + return true; // swallow the event + } else { + _lastKnownRealMouse = QCursor::pos(); + } + return false; // let the caller know to process the event } glm::vec2 ApplicationCompositor::getReticlePosition() { diff --git a/interface/src/ui/ApplicationCompositor.h b/interface/src/ui/ApplicationCompositor.h index 869e97ec60..bbe3db1264 100644 --- a/interface/src/ui/ApplicationCompositor.h +++ b/interface/src/ui/ApplicationCompositor.h @@ -98,8 +98,8 @@ public: ReticleInterface* getReticleInterface() { return _reticleInterface; } - void handleRealMouseMoveEvent(bool sendFakeEvent = true); - void trackRealMouseMoveEvent(); + /// return value - true means the caller should not process the event further + bool handleRealMouseMoveEvent(bool sendFakeEvent = true); void handleLeaveEvent(); QPointF getMouseEventPosition(QMouseEvent* event); From b0664b587f52dbaa312dc8dc8ccf2429642361ed Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 18 Feb 2016 15:39:38 -0800 Subject: [PATCH 22/72] bumped injector count --- examples/audioExamples/injectorLoadTest.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/audioExamples/injectorLoadTest.js b/examples/audioExamples/injectorLoadTest.js index 3842678590..3af54c4c48 100644 --- a/examples/audioExamples/injectorLoadTest.js +++ b/examples/audioExamples/injectorLoadTest.js @@ -13,8 +13,9 @@ Script.include("../libraries/utils.js"); -var numSoundsToPlayPerBatch = 1; -var timeBetweenBatch = 100; +var numSoundsToPlayPerBatch = 41 +var numSoundsPlaying = 0; +var timeBetweenBatch = 10000; // A green box represents an injector that is playing var basePosition = { @@ -58,6 +59,9 @@ function playSound() { position: position, volume: 0.1 }); + + print("INJECTOR VALUE: " + JSON.stringify(injector)); + totalInjectors++; var soundBox = Entities.addEntity({ From c3a687e294aa475dfbba0257d5e538186c7aeb0d Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 18 Feb 2016 16:06:53 -0800 Subject: [PATCH 23/72] ac test --- examples/audioExamples/injectorLoadTest.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/examples/audioExamples/injectorLoadTest.js b/examples/audioExamples/injectorLoadTest.js index 3af54c4c48..af4dcaecf7 100644 --- a/examples/audioExamples/injectorLoadTest.js +++ b/examples/audioExamples/injectorLoadTest.js @@ -15,7 +15,7 @@ Script.include("../libraries/utils.js"); var numSoundsToPlayPerBatch = 41 var numSoundsPlaying = 0; -var timeBetweenBatch = 10000; +var timeBetweenBatch = 100000; // A green box represents an injector that is playing var basePosition = { @@ -45,6 +45,10 @@ function playSounds() { for (var i = 0; i < numSoundsToPlayPerBatch; i++) { playSound(); } + + Script.setTimeout(function() { + numSoundsPlaying = 0; + }, 1500); print("EBL Total Number of Injectors: " + totalInjectors); Script.setTimeout(function() { @@ -57,11 +61,13 @@ function playSound() { var position = Vec3.sum(basePosition, {x: randFloat(-.1, .1), y: randFloat(-1, 1), z: randFloat(-3, -.1)}); var injector = Audio.playSound(testSound, { position: position, - volume: 0.1 + volume: 0.2 }); + numSoundsPlaying++; + print("NUM SOUNDS PLAYING: " + numSoundsPlaying); + print("*******************************************"); print("INJECTOR VALUE: " + JSON.stringify(injector)); - totalInjectors++; var soundBox = Entities.addEntity({ From bc0216633e45deab2e27246fca289a8c6ecc0db6 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 18 Feb 2016 16:10:12 -0800 Subject: [PATCH 24/72] more logging --- examples/audioExamples/injectorLoadTest.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/audioExamples/injectorLoadTest.js b/examples/audioExamples/injectorLoadTest.js index af4dcaecf7..cc9d47e17e 100644 --- a/examples/audioExamples/injectorLoadTest.js +++ b/examples/audioExamples/injectorLoadTest.js @@ -13,7 +13,7 @@ Script.include("../libraries/utils.js"); -var numSoundsToPlayPerBatch = 41 +var numSoundsToPlayPerBatch = 60 var numSoundsPlaying = 0; var timeBetweenBatch = 100000; // A green box represents an injector that is playing From 162be13914f1c44843fbc891e33c44825fc59751 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Thu, 18 Feb 2016 16:14:03 -0800 Subject: [PATCH 25/72] Don't keep adding signal connections. More logging. --- libraries/audio-client/src/AudioClient.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index f566c2d5df..da62645fec 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -110,6 +110,7 @@ AudioClient::AudioClient() : connect(&_receivedAudioStream, &MixedProcessedAudioStream::processSamples, this, &AudioClient::processReceivedSamples, Qt::DirectConnection); + connect(this, &AudioClient::changeDevice, this, [=](const QAudioDeviceInfo& outputDeviceInfo) { switchOutputToAudioDevice(outputDeviceInfo); }); _inputDevices = getDeviceNames(QAudio::AudioInput); _outputDevices = getDeviceNames(QAudio::AudioOutput); @@ -1042,7 +1043,6 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDevice _audioOutput->setBufferSize(requestedSize); connect(_audioOutput, &QAudioOutput::notify, this, &AudioClient::outputNotify); - connect(this, &AudioClient::changeDevice, this, [=](const QAudioDeviceInfo& outputDeviceInfo) { switchOutputToAudioDevice(outputDeviceInfo); }); _audioOutputIODevice.start(); _audioOutput->start(&_audioOutputIODevice); @@ -1151,6 +1151,12 @@ qint64 AudioClient::AudioOutputIODevice::readData(char * data, qint64 maxSize) { } int bytesAudioOutputUnplayed = _audio->_audioOutput->bufferSize() - _audio->_audioOutput->bytesFree(); + if (!bytesAudioOutputUnplayed) { + qCDebug(audioclient) << "empty audio buffer"; + } + if (!bytesWritten) { + qCDebug(audioclient) << "no audio written" << _audio->_audioOutput->bytesFree() << "free," << _audio->_audioOutput->bufferSize() << "buffer"; + } if (bytesAudioOutputUnplayed == 0 && bytesWritten == 0) { _unfulfilledReads++; } From d0660fc90a01893a0ac7a116f258ed917db91cde Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 18 Feb 2016 16:17:22 -0800 Subject: [PATCH 26/72] logging --- examples/audioExamples/injectorLoadTest.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/audioExamples/injectorLoadTest.js b/examples/audioExamples/injectorLoadTest.js index cc9d47e17e..d34117f56c 100644 --- a/examples/audioExamples/injectorLoadTest.js +++ b/examples/audioExamples/injectorLoadTest.js @@ -13,9 +13,9 @@ Script.include("../libraries/utils.js"); -var numSoundsToPlayPerBatch = 60 +var numSoundsToPlayPerBatch = 50 var numSoundsPlaying = 0; -var timeBetweenBatch = 100000; +var timeBetweenBatch = 30000; // A green box represents an injector that is playing var basePosition = { @@ -67,7 +67,8 @@ function playSound() { numSoundsPlaying++; print("NUM SOUNDS PLAYING: " + numSoundsPlaying); print("*******************************************"); - print("INJECTOR VALUE: " + JSON.stringify(injector)); + print("INJECTOR VALUE: ") + print(JSON.stringify(injector)); totalInjectors++; var soundBox = Entities.addEntity({ From adb33e7dcaf682d2c3fcb177364e11080ba83b05 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Thu, 18 Feb 2016 16:32:18 -0800 Subject: [PATCH 27/72] Up default initial buffer frame size to the value from before. --- libraries/audio-client/src/AudioClient.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index 3a93c1e1b3..d3145629ee 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -54,7 +54,7 @@ static const int NUM_AUDIO_CHANNELS = 2; -static const int DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 1; +static const int DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 3; static const int MIN_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 1; static const int MAX_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 20; static const int DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_ENABLED = true; From 4b29921e639423e87b09d9dc29915de4fde3d76d Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Thu, 18 Feb 2016 16:41:29 -0800 Subject: [PATCH 28/72] media! --- interface/resources/qml/controls/WebView.qml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/interface/resources/qml/controls/WebView.qml b/interface/resources/qml/controls/WebView.qml index c7ae322cba..6ff66d6192 100644 --- a/interface/resources/qml/controls/WebView.qml +++ b/interface/resources/qml/controls/WebView.qml @@ -11,6 +11,7 @@ WebEngineView { root.javaScriptConsoleMessage.connect(function(level, message, lineNumber, sourceID) { console.log("Web Window JS message: " + sourceID + " " + lineNumber + " " + message); }); + } // FIXME hack to get the URL with the auth token included. Remove when we move to Qt 5.6 @@ -36,6 +37,10 @@ WebEngineView { } } + onFeaturePermissionRequested: { + grantFeaturePermission(securityOrigin, feature, true); + } + onLoadingChanged: { // Required to support clicking on "hifi://" links if (WebEngineView.LoadStartedStatus == loadRequest.status) { From d73728ae78bf36d3f9598319a1a1fb016b24b356 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Thu, 18 Feb 2016 16:58:34 -0800 Subject: [PATCH 29/72] add to browser --- interface/resources/qml/Browser.qml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml index 382acc237c..110011d2c0 100644 --- a/interface/resources/qml/Browser.qml +++ b/interface/resources/qml/Browser.qml @@ -129,6 +129,10 @@ Window { id: webviewProfile storageName: "qmlUserBrowser" } + + onFeaturePermissionRequested: { + grantFeaturePermission(securityOrigin, feature, true); + } } } // item From 0de5c1cf71b638391811f12fcaae69bcfce964d1 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Thu, 18 Feb 2016 17:11:40 -0800 Subject: [PATCH 30/72] don't capture the mouse if you're not the active window or if a menu is popped up --- interface/src/Menu.cpp | 7 +++++++ interface/src/Menu.h | 5 +++++ interface/src/ui/ApplicationCompositor.cpp | 8 ++++++-- interface/src/ui/ApplicationCompositor.h | 2 ++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index caab3d52d4..48afdb4622 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -968,6 +968,7 @@ int Menu::positionBeforeSeparatorIfNeeded(MenuWrapper* menu, int requestedPositi return requestedPosition; } +bool Menu::_isSomeSubmenuShown = false; MenuWrapper* Menu::addMenu(const QString& menuName, const QString& grouping) { QStringList menuTree = menuName.split(">"); @@ -994,6 +995,12 @@ MenuWrapper* Menu::addMenu(const QString& menuName, const QString& grouping) { } QMenuBar::repaint(); + + // hook our show/hide for popup menus, so we can keep track of whether or not one + // of our submenus is currently showing. + connect(menu->_realMenu, &QMenu::aboutToShow, []() { _isSomeSubmenuShown = true; }); + connect(menu->_realMenu, &QMenu::aboutToHide, []() { _isSomeSubmenuShown = false; }); + return menu; } diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 6cc6121720..51a1542490 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -42,6 +42,7 @@ public: QAction* newAction() { return new QAction(_realMenu); } + private: MenuWrapper(QMenu* menu); @@ -117,6 +118,8 @@ public slots: void toggleDeveloperMenus(); void toggleAdvancedMenus(); + static bool isSomeSubmenuShown() { return _isSomeSubmenuShown; } + private: typedef void(*settingsAction)(Settings&, QAction&); static void loadAction(Settings& settings, QAction& action); @@ -142,6 +145,8 @@ private: bool isValidGrouping(const QString& grouping) const { return grouping == "Advanced" || grouping == "Developer"; } QHash _groupingVisible; QHash> _groupingActions; + + static bool _isSomeSubmenuShown; }; namespace MenuOption { diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 4588a24ac0..2ba5d4ba98 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -308,9 +308,13 @@ QPointF ApplicationCompositor::getMouseEventPosition(QMouseEvent* event) { return event->localPos(); } +bool ApplicationCompositor::shouldCaptureMouse() const { + // if we're in HMD mode, and some window of ours is active, but we're not currently showing a popup menu + return qApp->isHMDMode() && QApplication::activeWindow() && !Menu::isSomeSubmenuShown(); +} void ApplicationCompositor::handleLeaveEvent() { - if (qApp->isHMDMode()) { + if (shouldCaptureMouse()) { auto applicationGeometry = qApp->getApplicationGeometry(); _ignoreMouseMove = true; auto sendToPos = applicationGeometry.center(); @@ -328,7 +332,7 @@ bool ApplicationCompositor::handleRealMouseMoveEvent(bool sendFakeEvent) { } // If we're in HMD mode - if (qApp->isHMDMode()) { + if (shouldCaptureMouse()) { auto newPosition = QCursor::pos(); auto changeInRealMouse = newPosition - _lastKnownRealMouse; auto newReticlePosition = _reticlePositionInHMD + toGlm(changeInRealMouse); diff --git a/interface/src/ui/ApplicationCompositor.h b/interface/src/ui/ApplicationCompositor.h index bbe3db1264..c706d123f2 100644 --- a/interface/src/ui/ApplicationCompositor.h +++ b/interface/src/ui/ApplicationCompositor.h @@ -105,6 +105,8 @@ public: private: + bool shouldCaptureMouse() const; + void displayOverlayTextureStereo(RenderArgs* renderArgs, float aspectRatio, float fov); void bindCursorTexture(gpu::Batch& batch, uint8_t cursorId = 0); void buildHemiVertices(const float fov, const float aspectRatio, const int slices, const int stacks); From 981d4d37cad84f0de243ea62a2f65c5fd547c20f Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 18 Feb 2016 17:45:52 -0800 Subject: [PATCH 31/72] Update render/debug.js - Add a toggle for the entire UI - Set items sliders minimums to -1 - Fix off-by-one with debug buffer radios --- examples/utilities/tools/render/debug.js | 3 - examples/utilities/tools/render/main.qml | 169 ++++++++++++----------- 2 files changed, 90 insertions(+), 82 deletions(-) diff --git a/examples/utilities/tools/render/debug.js b/examples/utilities/tools/render/debug.js index f195c607a4..8aac9c270e 100644 --- a/examples/utilities/tools/render/debug.js +++ b/examples/utilities/tools/render/debug.js @@ -14,9 +14,6 @@ Render.RenderShadowTask.enabled = true; var RDT = Render.RenderDeferredTask; RDT.AmbientOcclusion.enabled = true; RDT.DebugDeferredBuffer.enabled = false; -["DrawOpaqueDeferred", "DrawTransparentDeferred", "DrawOverlay3DOpaque", "DrawOverlay3DTransparent"] - .map(function(name) { return RDT[name]; }) - .forEach(function(job) { job.maxDrawn = job.numDrawn; }); // Set up the qml ui var qml = Script.resolvePath('main.qml'); diff --git a/examples/utilities/tools/render/main.qml b/examples/utilities/tools/render/main.qml index 9e825ad4df..22f263b2d0 100644 --- a/examples/utilities/tools/render/main.qml +++ b/examples/utilities/tools/render/main.qml @@ -12,98 +12,109 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 Column { - spacing: 8 - - Repeater { - model: [ "Opaque:DrawOpaqueDeferred", "Transparent:DrawTransparentDeferred", - "Opaque Overlays:DrawOverlay3DOpaque", "Transparent Overlays:DrawOverlay3DTransparent" ] - ConfigSlider { - label: qsTr(modelData.split(":")[0]) - integral: true - config: Render.getConfig(modelData.split(":")[1]) - property: "maxDrawn" - max: config.numDrawn - } - } - - Row { - CheckBox { - text: qsTr("Display Status") - onCheckedChanged: { Render.getConfig("DrawStatus").showDisplay = checked } - } - CheckBox { - text: qsTr("Network/Physics Status") - onCheckedChanged: { Render.getConfig("DrawStatus").showNetwork = checked } - } - } - - ConfigSlider { - label: qsTr("Tone Mapping Exposure") - config: Render.getConfig("ToneMapping") - property: "exposure" - min: -10; max: 10 + id: root + spacing: 16 + Switch { + checked: true + onClicked: ui.visible = checked } Column { - id: ambientOcclusion - property var config: Render.getConfig("AmbientOcclusion") + id: ui + spacing: 8 - Label { text: qsTr("Ambient Occlusion") } - // TODO: Add gpuTimer - CheckBox { text: qsTr("Dithering"); checked: ambientOcclusion.config.ditheringEnabled } Repeater { - model: [ - "Resolution Level:resolutionLevel:4", - "Obscurance Level:obscuranceLevel:1", - "Radius:radius:2", - "Falloff Bias:falloffBias:0.2", - "Edge Sharpness:edgeSharpness:1", - "Blur Radius:blurRadius:6", - "Blur Deviation:blurDeviation:3" - ] - ConfigSlider { - label: qsTr(modelData.split(":")[0]) - config: ambientOcclusion.config - property: modelData.split(":")[1] - max: modelData.split(":")[2] - } - } - Repeater { - model: [ - "Samples:numSamples:32", - "Spiral Turns:numSpiralTurns:30:" - ] + model: [ "Opaque:DrawOpaqueDeferred", "Transparent:DrawTransparentDeferred", + "Opaque Overlays:DrawOverlay3DOpaque", "Transparent Overlays:DrawOverlay3DTransparent" ] ConfigSlider { label: qsTr(modelData.split(":")[0]) integral: true - config: ambientOcclusion.config - property: modelData.split(":")[1] - max: modelData.split(":")[2] + config: Render.getConfig(modelData.split(":")[1]) + property: "maxDrawn" + max: config.numDrawn + min: -1 } } - } - Column { - id: debug - property var config: Render.getConfig("DebugDeferredBuffer") - - function setDebugMode(mode) { - debug.config.enabled = (mode != 0); - debug.config.mode = mode; + Row { + CheckBox { + text: qsTr("Display Status") + onCheckedChanged: { Render.getConfig("DrawStatus").showDisplay = checked } + } + CheckBox { + text: qsTr("Network/Physics Status") + onCheckedChanged: { Render.getConfig("DrawStatus").showNetwork = checked } + } } - Label { text: qsTr("Debug Buffer") } - ExclusiveGroup { id: bufferGroup } - Repeater { - model: [ - "Off", "Diffuse", "Metallic", "Roughness", "Normal", "Depth", - "Lighting", "Shadow", "Pyramid Depth", "Ambient Occlusion", "Custom Shader" - ] - RadioButton { - text: qsTr(modelData) - exclusiveGroup: bufferGroup - checked: index == 0 - onCheckedChanged: if (checked) debug.setDebugMode(index); + ConfigSlider { + label: qsTr("Tone Mapping Exposure") + config: Render.getConfig("ToneMapping") + property: "exposure" + min: -10; max: 10 + } + + Column { + id: ambientOcclusion + property var config: Render.getConfig("AmbientOcclusion") + + Label { text: qsTr("Ambient Occlusion") } + // TODO: Add gpuTimer + CheckBox { text: qsTr("Dithering"); checked: ambientOcclusion.config.ditheringEnabled } + Repeater { + model: [ + "Resolution Level:resolutionLevel:4", + "Obscurance Level:obscuranceLevel:1", + "Radius:radius:2", + "Falloff Bias:falloffBias:0.2", + "Edge Sharpness:edgeSharpness:1", + "Blur Radius:blurRadius:6", + "Blur Deviation:blurDeviation:3" + ] + ConfigSlider { + label: qsTr(modelData.split(":")[0]) + config: ambientOcclusion.config + property: modelData.split(":")[1] + max: modelData.split(":")[2] + } + } + Repeater { + model: [ + "Samples:numSamples:32", + "Spiral Turns:numSpiralTurns:30:" + ] + ConfigSlider { + label: qsTr(modelData.split(":")[0]) + integral: true + config: ambientOcclusion.config + property: modelData.split(":")[1] + max: modelData.split(":")[2] + } + } + } + + Column { + id: debug + property var config: Render.getConfig("DebugDeferredBuffer") + + function setDebugMode(mode) { + debug.config.enabled = (mode != 0); + debug.config.mode = mode; + } + + Label { text: qsTr("Debug Buffer") } + ExclusiveGroup { id: bufferGroup } + Repeater { + model: [ + "Off", "Diffuse", "Metallic", "Roughness", "Normal", "Depth", + "Lighting", "Shadow", "Pyramid Depth", "Ambient Occlusion", "Custom Shader" + ] + RadioButton { + text: qsTr(modelData) + exclusiveGroup: bufferGroup + checked: index == 0 + onCheckedChanged: if (checked && index > 0) debug.setDebugMode(index - 1); + } } } } From 93f61fce7aa0f36f0e6bc2427dbf7bd953c7451a Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Thu, 18 Feb 2016 18:00:04 -0800 Subject: [PATCH 32/72] OpenVRDisplayPlugin: predict poses for better tracking Extrapolate the next set of poses for HMD and hand controllers. Currently we predict 44ms into the future, this seems too high, however it was discovered by inspection to be the best value. Obviously there is a source of latency that we need to track down, however even with this latency, it is a much improved experience. --- plugins/openvr/src/OpenVrDisplayPlugin.cpp | 48 ++++++++++++---------- plugins/openvr/src/OpenVrDisplayPlugin.h | 2 +- 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index 7575cc83e7..353b248302 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -30,7 +30,6 @@ const QString OpenVrDisplayPlugin::NAME("OpenVR (Vive)"); const QString StandingHMDSensorMode = "Standing HMD Sensor Mode"; // this probably shouldn't be hardcoded here static vr::IVRCompositor* _compositor{ nullptr }; -static vr::TrackedDevicePose_t _presentThreadTrackedDevicePose[vr::k_unMaxTrackedDeviceCount]; vr::TrackedDevicePose_t _trackedDevicePose[vr::k_unMaxTrackedDeviceCount]; mat4 _trackedDevicePoseMat4[vr::k_unMaxTrackedDeviceCount]; static mat4 _sensorResetMat; @@ -43,12 +42,12 @@ bool OpenVrDisplayPlugin::isSupported() const { void OpenVrDisplayPlugin::activate() { _container->setIsOptionChecked(StandingHMDSensorMode, true); - if (!_hmd) { - _hmd = acquireOpenVrSystem(); + if (!_system) { + _system = acquireOpenVrSystem(); } - Q_ASSERT(_hmd); + Q_ASSERT(_system); - _hmd->GetRecommendedRenderTargetSize(&_renderTargetSize.x, &_renderTargetSize.y); + _system->GetRecommendedRenderTargetSize(&_renderTargetSize.x, &_renderTargetSize.y); // Recommended render target size is per-eye, so double the X size for // left + right eyes _renderTargetSize.x *= 2; @@ -56,8 +55,8 @@ void OpenVrDisplayPlugin::activate() { { Lock lock(_poseMutex); openvr_for_each_eye([&](vr::Hmd_Eye eye) { - _eyeOffsets[eye] = toGlm(_hmd->GetEyeToHeadTransform(eye)); - _eyeProjections[eye] = toGlm(_hmd->GetProjectionMatrix(eye, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, vr::API_OpenGL)); + _eyeOffsets[eye] = toGlm(_system->GetEyeToHeadTransform(eye)); + _eyeProjections[eye] = toGlm(_system->GetProjectionMatrix(eye, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, vr::API_OpenGL)); }); // FIXME Calculate the proper combined projection by using GetProjectionRaw values from both eyes _cullingProjection = _eyeProjections[0]; @@ -71,9 +70,9 @@ void OpenVrDisplayPlugin::activate() { void OpenVrDisplayPlugin::deactivate() { _container->setIsOptionChecked(StandingHMDSensorMode, false); - if (_hmd) { + if (_system) { releaseOpenVrSystem(); - _hmd = nullptr; + _system = nullptr; } _compositor = nullptr; HmdDisplayPlugin::deactivate(); @@ -96,9 +95,24 @@ void OpenVrDisplayPlugin::resetSensors() { _sensorResetMat = glm::inverse(cancelOutRollAndPitch(m)); } - glm::mat4 OpenVrDisplayPlugin::getHeadPose(uint32_t frameIndex) const { - Lock lock(_poseMutex); + + float displayFrequency = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_DisplayFrequency_Float); + float frameDuration = 1.f / displayFrequency; + float vsyncToPhotons = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_SecondsFromVsyncToPhotons_Float); + + // TODO: this seems awfuly long, 44ms total, but it produced the best results. + const float NUM_PREDICTION_FRAMES = 3.0f; + float predictedSecondsFromNow = NUM_PREDICTION_FRAMES * frameDuration + vsyncToPhotons; + + vr::TrackedDevicePose_t predictedTrackedDevicePose[vr::k_unMaxTrackedDeviceCount]; + _system->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseSeated, predictedSecondsFromNow, predictedTrackedDevicePose, vr::k_unMaxTrackedDeviceCount); + + // copy and process predictedTrackedDevicePoses + for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) { + _trackedDevicePose[i] = predictedTrackedDevicePose[i]; + _trackedDevicePoseMat4[i] = _sensorResetMat * toGlm(_trackedDevicePose[i].mDeviceToAbsoluteTracking); + } return _trackedDevicePoseMat4[0]; } @@ -114,16 +128,8 @@ void OpenVrDisplayPlugin::internalPresent() { glFinish(); - _compositor->WaitGetPoses(_presentThreadTrackedDevicePose, vr::k_unMaxTrackedDeviceCount, nullptr, 0); - - { - // copy and process _presentThreadTrackedDevicePoses - Lock lock(_poseMutex); - for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) { - _trackedDevicePose[i] = _presentThreadTrackedDevicePose[i]; - _trackedDevicePoseMat4[i] = _sensorResetMat * toGlm(_trackedDevicePose[i].mDeviceToAbsoluteTracking); - } - } + vr::TrackedDevicePose_t currentTrackedDevicePose[vr::k_unMaxTrackedDeviceCount]; + _compositor->WaitGetPoses(currentTrackedDevicePose, vr::k_unMaxTrackedDeviceCount, nullptr, 0); // Handle the mirroring in the base class HmdDisplayPlugin::internalPresent(); diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.h b/plugins/openvr/src/OpenVrDisplayPlugin.h index 9c480e48f7..4344c3c48f 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.h +++ b/plugins/openvr/src/OpenVrDisplayPlugin.h @@ -35,7 +35,7 @@ protected: virtual void internalPresent() override; private: - vr::IVRSystem* _hmd { nullptr }; + vr::IVRSystem* _system { nullptr }; static const QString NAME; mutable Mutex _poseMutex; }; From 33a232edde27abbdf91483ecb6f03af8f965dcd8 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 18 Feb 2016 18:17:37 -0800 Subject: [PATCH 33/72] got rid of magic numbers --- examples/audioExamples/injectorLoadTest.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/examples/audioExamples/injectorLoadTest.js b/examples/audioExamples/injectorLoadTest.js index d34117f56c..59ddea6a3c 100644 --- a/examples/audioExamples/injectorLoadTest.js +++ b/examples/audioExamples/injectorLoadTest.js @@ -13,7 +13,7 @@ Script.include("../libraries/utils.js"); -var numSoundsToPlayPerBatch = 50 +var numSoundsToPlayPerBatch = 35 var numSoundsPlaying = 0; var timeBetweenBatch = 30000; // A green box represents an injector that is playing @@ -28,16 +28,19 @@ var soundBoxes = []; var testSound = SoundCache.getSound("https://s3-us-west-1.amazonaws.com/hifi-content/eric/Sounds/dove.wav"); var totalInjectors = 0; +var clipDuration; if(!testSound.downloaded) { print("SOUND IS NOT READY YET") testSound.ready.connect(function() { playSounds(); + clipDuration = testSound.duration; }); } else { // otherwise play sounds right away playSounds(); + clipDuration = testSound.duration; } function playSounds() { @@ -48,7 +51,7 @@ function playSounds() { Script.setTimeout(function() { numSoundsPlaying = 0; - }, 1500); + }, clipDuration); print("EBL Total Number of Injectors: " + totalInjectors); Script.setTimeout(function() { From 2dd1cf2f15677e07214cefad20fa98200b1bffb4 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 18 Feb 2016 18:21:26 -0800 Subject: [PATCH 34/72] Update Render.fromJSON to Render.load --- examples/utilities/tools/render/debug.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/utilities/tools/render/debug.js b/examples/utilities/tools/render/debug.js index 8aac9c270e..eba967491b 100644 --- a/examples/utilities/tools/render/debug.js +++ b/examples/utilities/tools/render/debug.js @@ -36,4 +36,4 @@ function setDebugBufferSize(x) { Render.RenderDeferredTask.DebugDeferredBuffer.size = {x: x, y: -1, z: 1, w: 1}; } -Script.scriptEnding.connect(function() { Render.fromJSON(oldConfig); } ); +Script.scriptEnding.connect(function() { Render.load(oldConfig); } ); From bc5d4cfb7f7c0a2420c1514d5e43a460329036cd Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Thu, 18 Feb 2016 20:20:30 -0800 Subject: [PATCH 35/72] better handling of mouse capture to account for overlapping child windows --- interface/src/ui/ApplicationCompositor.cpp | 29 +++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 2ba5d4ba98..370a5d91fd 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -315,9 +315,31 @@ bool ApplicationCompositor::shouldCaptureMouse() const { void ApplicationCompositor::handleLeaveEvent() { if (shouldCaptureMouse()) { - auto applicationGeometry = qApp->getApplicationGeometry(); + QWidget* mainWidget = (QWidget*)qApp->getWindow(); + QRect mainWidgetFrame = qApp->getApplicationGeometry(); + QRect uncoveredRect = mainWidgetFrame; + foreach(QWidget* widget, QApplication::topLevelWidgets()) { + if (widget->isWindow() && widget->isVisible() && widget != mainWidget) { + QRect widgetFrame = widget->frameGeometry(); + if (widgetFrame.intersects(uncoveredRect)) { + QRect intersection = uncoveredRect & widgetFrame; + if (intersection.top() > uncoveredRect.top()) { + uncoveredRect.setBottom(intersection.top() - 1); + } else if (intersection.bottom() < uncoveredRect.bottom()) { + uncoveredRect.setTop(intersection.bottom() + 1); + } + + if (intersection.left() > uncoveredRect.left()) { + uncoveredRect.setRight(intersection.left() - 1); + } else if (intersection.right() < uncoveredRect.right()) { + uncoveredRect.setLeft(intersection.right() + 1); + } + } + } + } + _ignoreMouseMove = true; - auto sendToPos = applicationGeometry.center(); + auto sendToPos = uncoveredRect.center(); QCursor::setPos(sendToPos); _lastKnownRealMouse = sendToPos; } @@ -336,8 +358,9 @@ bool ApplicationCompositor::handleRealMouseMoveEvent(bool sendFakeEvent) { auto newPosition = QCursor::pos(); auto changeInRealMouse = newPosition - _lastKnownRealMouse; auto newReticlePosition = _reticlePositionInHMD + toGlm(changeInRealMouse); - _lastKnownRealMouse = newPosition; setReticlePosition(newReticlePosition, sendFakeEvent); + _ignoreMouseMove = true; + QCursor::setPos(QPoint(_lastKnownRealMouse.x(), _lastKnownRealMouse.y())); // move cursor back to where it was return true; // swallow the event } else { _lastKnownRealMouse = QCursor::pos(); From dd8e5fd199343ee11ead37a02a754a632bd6c780 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Thu, 18 Feb 2016 20:21:42 -0800 Subject: [PATCH 36/72] removed dead code --- libraries/gl/src/gl/OffscreenQmlSurface.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index ea3fb63d66..42eea08057 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -573,10 +573,8 @@ bool OffscreenQmlSurface::eventFilter(QObject* originalDestination, QEvent* even case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseMove: { - //qDebug() << __FUNCTION__ << "event:" << event; QMouseEvent* mouseEvent = static_cast(event); QPointF transformedPos = mapToVirtualScreen(mouseEvent->localPos(), originalDestination); - //qDebug() << __FUNCTION__ << "transformedPos:" << transformedPos; QMouseEvent mappedEvent(mouseEvent->type(), transformedPos, mouseEvent->screenPos(), mouseEvent->button(), From d1e1067e5a2c8245aa600cab777b5ae70a1b585b Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Thu, 18 Feb 2016 22:30:31 -0800 Subject: [PATCH 37/72] allow hydra mouse to know the correct size of screen to target --- examples/controllers/reticleHandRotationTest.js | 5 +++-- interface/src/ui/ApplicationCompositor.cpp | 14 +++++++++++++- interface/src/ui/ApplicationCompositor.h | 12 +++++++++--- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/examples/controllers/reticleHandRotationTest.js b/examples/controllers/reticleHandRotationTest.js index 0f684a37f0..631486d1a3 100644 --- a/examples/controllers/reticleHandRotationTest.js +++ b/examples/controllers/reticleHandRotationTest.js @@ -53,8 +53,9 @@ Script.update.connect(function(deltaTime) { var poseLeft = Controller.getPoseValue(Controller.Standard.LeftHand); // NOTE: hack for now - var screenSizeX = 1920; - var screenSizeY = 1080; + var screenSize = Reticle.maximumPosition; + var screenSizeX = screenSize.x; + var screenSizeY = screenSize.y; var rotatedRight = Vec3.multiplyQbyV(poseRight.rotation, Vec3.UNIT_NEG_Y); var rotatedLeft = Vec3.multiplyQbyV(poseLeft.rotation, Vec3.UNIT_NEG_Y); diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 370a5d91fd..a083dbf15f 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -401,6 +401,18 @@ void ApplicationCompositor::setReticlePosition(glm::vec2 position, bool sendFake } } +#include + +glm::vec2 ApplicationCompositor::getReticleMaximumPosition() const { + glm::vec2 result; + if (qApp->isHMDMode()) { + result = glm::vec2(VIRTUAL_SCREEN_SIZE_X, VIRTUAL_SCREEN_SIZE_Y); + } else { + QRect rec = QApplication::desktop()->screenGeometry(); + result = glm::vec2(rec.right(), rec.bottom()); + } + return result; +} // FIXME - this probably is hella buggy and probably doesn't work correctly // we should kill it asap. @@ -571,7 +583,7 @@ glm::vec2 ApplicationCompositor::screenToSpherical(const glm::vec2& screenPos) { } glm::vec2 ApplicationCompositor::sphericalToScreen(const glm::vec2& sphericalPos) { - glm::uvec2 screenSize { VIRTUAL_SCREEN_SIZE_X, VIRTUAL_SCREEN_SIZE_Y }; // = qApp->getCanvasSize(); + glm::uvec2 screenSize { VIRTUAL_SCREEN_SIZE_X, VIRTUAL_SCREEN_SIZE_Y }; glm::vec2 result = sphericalPos; result.x *= -1.0f; result /= MOUSE_RANGE; diff --git a/interface/src/ui/ApplicationCompositor.h b/interface/src/ui/ApplicationCompositor.h index c706d123f2..ff5477e30d 100644 --- a/interface/src/ui/ApplicationCompositor.h +++ b/interface/src/ui/ApplicationCompositor.h @@ -96,6 +96,8 @@ public: Q_INVOKABLE glm::vec2 getReticlePosition(); Q_INVOKABLE void setReticlePosition(glm::vec2 position, bool sendFakeEvent = true); + Q_INVOKABLE glm::vec2 getReticleMaximumPosition() const; + ReticleInterface* getReticleInterface() { return _reticleInterface; } /// return value - true means the caller should not process the event further @@ -160,9 +162,11 @@ private: // Scripting interface available to control the Reticle class ReticleInterface : public QObject { Q_OBJECT - Q_PROPERTY(glm::vec2 position READ getPosition WRITE setPosition) - Q_PROPERTY(bool visible READ getVisible WRITE setVisible) - Q_PROPERTY(float depth READ getDepth WRITE setDepth) + Q_PROPERTY(glm::vec2 position READ getPosition WRITE setPosition) + Q_PROPERTY(bool visible READ getVisible WRITE setVisible) + Q_PROPERTY(float depth READ getDepth WRITE setDepth) + Q_PROPERTY(glm::vec2 maximumPosition READ getMaximumPosition) + public: ReticleInterface(ApplicationCompositor* outer) : QObject(outer), _compositor(outer) {} @@ -174,6 +178,8 @@ public: Q_INVOKABLE glm::vec2 getPosition() { return _compositor->getReticlePosition(); } Q_INVOKABLE void setPosition(glm::vec2 position) { _compositor->setReticlePosition(position); } + + Q_INVOKABLE glm::vec2 getMaximumPosition() { return _compositor->getReticleMaximumPosition(); } private: ApplicationCompositor* _compositor; }; From 01d3977bf148e39d969c2be1969e07e88552acca Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 19 Feb 2016 10:04:58 -0800 Subject: [PATCH 38/72] make avatars shrink faster --- interface/src/avatar/AvatarManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 6da4481840..8e48237b8e 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -162,7 +162,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { void AvatarManager::simulateAvatarFades(float deltaTime) { QVector::iterator fadingIterator = _avatarFades.begin(); - const float SHRINK_RATE = 0.9f; + const float SHRINK_RATE = 0.15f; const float MIN_FADE_SCALE = MIN_AVATAR_SCALE; render::ScenePointer scene = qApp->getMain3DScene(); From ee5a82f9b80af83fd3e454cd43892958d6e21b8f Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 19 Feb 2016 10:05:22 -0800 Subject: [PATCH 39/72] call simulate from setScaleInternal rather than just initJointTransforms so the scale change is visible --- libraries/render-utils/src/Model.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 91c9ec623d..1f6e25f386 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -92,7 +92,7 @@ void Model::setScale(const glm::vec3& scale) { _scaledToFit = false; } -const float METERS_PER_MILLIMETER = 0.01f; +const float METERS_PER_MILLIMETER = 0.01f; void Model::setScaleInternal(const glm::vec3& scale) { if (glm::distance(_scale, scale) > METERS_PER_MILLIMETER) { @@ -100,7 +100,7 @@ void Model::setScaleInternal(const glm::vec3& scale) { if (_scale.x == 0.0f || _scale.y == 0.0f || _scale.z == 0.0f) { assert(false); } - initJointTransforms(); + simulate(0.0f, true); } } From fcdc6dd6fa34de97552a8d1a03272862832ae0ad Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Fri, 19 Feb 2016 10:54:53 -0800 Subject: [PATCH 40/72] When we don't make an audo injector (because we're at a limit), make sure the value returned to scripts is null. --- libraries/script-engine/src/AudioScriptingInterface.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libraries/script-engine/src/AudioScriptingInterface.cpp b/libraries/script-engine/src/AudioScriptingInterface.cpp index a660e918a9..7e7ca77b88 100644 --- a/libraries/script-engine/src/AudioScriptingInterface.cpp +++ b/libraries/script-engine/src/AudioScriptingInterface.cpp @@ -45,8 +45,11 @@ ScriptAudioInjector* AudioScriptingInterface::playSound(Sound* sound, const Audi // stereo option isn't set from script, this comes from sound metadata or filename AudioInjectorOptions optionsCopy = injectorOptions; optionsCopy.stereo = sound->isStereo(); - - return new ScriptAudioInjector(AudioInjector::playSound(sound->getByteArray(), optionsCopy, _localAudioInterface)); + auto injector = AudioInjector::playSound(sound->getByteArray(), optionsCopy, _localAudioInterface); + if (!injector) { + return NULL; + } + return new ScriptAudioInjector(injector); } else { qCDebug(scriptengine) << "AudioScriptingInterface::playSound called with null Sound object."; From fea60499d44008df457fb44cf30fcc6787ad7f8b Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 19 Feb 2016 11:32:59 -0800 Subject: [PATCH 41/72] rename poorly named variable --- libraries/render-utils/src/Model.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 1f6e25f386..3b741ac734 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -92,10 +92,10 @@ void Model::setScale(const glm::vec3& scale) { _scaledToFit = false; } -const float METERS_PER_MILLIMETER = 0.01f; +const float SCALE_CHANGE_EPSILON = 0.01f; void Model::setScaleInternal(const glm::vec3& scale) { - if (glm::distance(_scale, scale) > METERS_PER_MILLIMETER) { + if (glm::distance(_scale, scale) > SCALE_CHANGE_EPSILON) { _scale = scale; if (_scale.x == 0.0f || _scale.y == 0.0f || _scale.z == 0.0f) { assert(false); From 30b4eace95dcddfc374b91baf3b1d1857201a1d6 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Fri, 19 Feb 2016 11:52:07 -0800 Subject: [PATCH 42/72] Remove LOD PID-related preferences and the related toggling of preferences. --- interface/resources/qml/Stats.qml | 8 +------- interface/src/Application.cpp | 6 +----- interface/src/LODManager.cpp | 23 ----------------------- interface/src/LODManager.h | 3 --- interface/src/ui/PreferencesDialog.cpp | 20 -------------------- interface/src/ui/Stats.cpp | 2 -- interface/src/ui/Stats.h | 7 ------- 7 files changed, 2 insertions(+), 67 deletions(-) diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index 35738c56b1..d2f78191ea 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -267,15 +267,9 @@ Item { Text { color: root.fontColor; font.pixelSize: root.fontSize - visible: root.showAcuity + visible: root.expanded text: "LOD: " + root.lodStatus; } - Text { - color: root.fontColor; - font.pixelSize: root.fontSize - visible: root.expanded && !root.showAcuity - text: root.lodStatsRenderText; - } } } } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c202331041..0d9fde5176 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3082,11 +3082,7 @@ void Application::update(float deltaTime) { bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::update()"); - if (DependencyManager::get()->getUseAcuity()) { - updateLOD(); - } else { - DependencyManager::get()->updatePIDRenderDistance(getTargetFrameRate(), getLastInstanteousFps(), deltaTime, isThrottleRendering()); - } + updateLOD(); { PerformanceTimer perfTimer("devices"); diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index 389e43a5ff..2644e55bfb 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -237,18 +237,12 @@ QString LODManager::getLODFeedbackText() { static float renderDistance = (float)TREE_SCALE; static int renderedCount = 0; static int lastRenderedCount = 0; -bool LODManager::getUseAcuity() { return lodPreference.get() == (int)LODManager::LODPreference::acuity; } -void LODManager::setUseAcuity(bool newValue) { lodPreference.set(newValue ? (int)LODManager::LODPreference::acuity : (int)LODManager::LODPreference::pid); } float LODManager::getRenderDistance() { return renderDistance; } int LODManager::getRenderedCount() { return lastRenderedCount; } -QString LODManager::getLODStatsRenderText() { - const QString label = "Rendered objects: "; - return label + QString::number(getRenderedCount()) + " w/in " + QString::number((int)getRenderDistance()) + "m"; -} // compare autoAdjustLOD() void LODManager::updatePIDRenderDistance(float targetFps, float measuredFps, float deltaTime, bool isThrottled) { float distance; @@ -270,17 +264,6 @@ void LODManager::updatePIDRenderDistance(float targetFps, float measuredFps, flo } bool LODManager::shouldRender(const RenderArgs* args, const AABox& bounds) { - // NOTE: this branch of code is the alternate form of LOD that uses PID controllers. - if (!getUseAcuity()) { - float distanceToCamera = glm::length(bounds.calcCenter() - args->_viewFrustum->getPosition()); - float largestDimension = bounds.getLargestDimension(); - const float scenerySize = 300; // meters - bool isRendered = (largestDimension > scenerySize) || // render scenery regardless of distance - (distanceToCamera < renderDistance + largestDimension); - renderedCount += isRendered ? 1 : 0; - return isRendered; - } - // FIXME - eventually we want to use the render accuracy as an indicator for the level of detail // to use in rendering. float renderAccuracy = args->_viewFrustum->calculateRenderAccuracy(bounds, args->_sizeScale, args->_boundaryLevelAdjust); @@ -299,12 +282,6 @@ void LODManager::setBoundaryLevelAdjust(int boundaryLevelAdjust) { void LODManager::loadSettings() { setDesktopLODDecreaseFPS(desktopLODDecreaseFPS.get()); setHMDLODDecreaseFPS(hmdLODDecreaseFPS.get()); - - if (lodPreference.get() == (int)LODManager::LODPreference::unspecified) { - setUseAcuity((getDesktopLODDecreaseFPS() != DEFAULT_DESKTOP_LOD_DOWN_FPS) || (getHMDLODDecreaseFPS() != DEFAULT_HMD_LOD_DOWN_FPS)); - } - Menu::getInstance()->getActionForOption(MenuOption::LodTools)->setEnabled(getUseAcuity()); - Menu::getInstance()->getSubMenuFromName(MenuOption::RenderResolution, Menu::getInstance()->getSubMenuFromName("Render", Menu::getInstance()->getMenu("Developer")))->setEnabled(getUseAcuity()); } void LODManager::saveSettings() { diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h index 4863324161..a9fabe8799 100644 --- a/interface/src/LODManager.h +++ b/interface/src/LODManager.h @@ -81,8 +81,6 @@ public: acuity, unspecified }; - static bool getUseAcuity(); - static void setUseAcuity(bool newValue); Q_INVOKABLE void setRenderDistanceKP(float newValue) { _renderDistanceController.setKP(newValue); } Q_INVOKABLE void setRenderDistanceKI(float newValue) { _renderDistanceController.setKI(newValue); } Q_INVOKABLE void setRenderDistanceKD(float newValue) { _renderDistanceController.setKD(newValue); } @@ -95,7 +93,6 @@ public: void updatePIDRenderDistance(float targetFps, float measuredFps, float deltaTime, bool isThrottled); float getRenderDistance(); int getRenderedCount(); - QString getLODStatsRenderText(); static bool shouldRender(const RenderArgs* args, const AABox& bounds); void autoAdjustLOD(float currentFPS); diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 80f2989127..4278fa8db9 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -87,13 +87,6 @@ void setupPreferences() { } static const QString LOD_TUNING("Level of Detail Tuning"); - CheckPreference* acuityToggle; - { - auto getter = []()->bool { return DependencyManager::get()->getUseAcuity(); }; - auto setter = [](bool value) { DependencyManager::get()->setUseAcuity(value); }; - preferences->addPreference(acuityToggle = new CheckPreference(LOD_TUNING, "Render based on visual acuity", getter, setter)); - } - { auto getter = []()->float { return DependencyManager::get()->getDesktopLODDecreaseFPS(); }; auto setter = [](float value) { DependencyManager::get()->setDesktopLODDecreaseFPS(value); }; @@ -101,7 +94,6 @@ void setupPreferences() { preference->setMin(0); preference->setMax(120); preference->setStep(1); - preference->setEnabler(acuityToggle); preferences->addPreference(preference); } @@ -112,18 +104,6 @@ void setupPreferences() { preference->setMin(0); preference->setMax(120); preference->setStep(1); - preference->setEnabler(acuityToggle); - preferences->addPreference(preference); - } - - { - auto getter = []()->float { return 1.0f / DependencyManager::get()->getRenderDistanceInverseHighLimit(); }; - auto setter = [](float value) { DependencyManager::get()->setRenderDistanceInverseHighLimit(1.0f / value); }; - auto preference = new SpinnerPreference(LOD_TUNING, "Minimum Display Distance", getter, setter); - preference->setMin(5); - preference->setMax(32768); - preference->setStep(1); - preference->setEnabler(acuityToggle, true); preferences->addPreference(preference); } diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 1ee26a865d..c9c4c68dc9 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -283,9 +283,7 @@ void Stats::updateStats(bool force) { STAT_UPDATE(localLeaves, (int)OctreeElement::getLeafNodeCount()); // LOD Details STAT_UPDATE(lodStatus, "You can see " + DependencyManager::get()->getLODFeedbackText()); - STAT_UPDATE(lodStatsRenderText, DependencyManager::get()->getLODStatsRenderText()); } - STAT_UPDATE(showAcuity, (_expanded || force) && DependencyManager::get()->getUseAcuity()); bool performanceTimerIsActive = PerformanceTimer::isActive(); bool displayPerf = _expanded && Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails); diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index bebfbf6f70..ba3c8f2391 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -30,7 +30,6 @@ class Stats : public QQuickItem { Q_PROPERTY(QString monospaceFont READ monospaceFont CONSTANT) Q_PROPERTY(float audioPacketlossUpstream READ getAudioPacketLossUpstream) Q_PROPERTY(float audioPacketlossDownstream READ getAudioPacketLossDownstream) - Q_PROPERTY(bool showAcuity READ getShowAcuity WRITE setShowAcuity NOTIFY showAcuityChanged) STATS_PROPERTY(int, serverCount, 0) STATS_PROPERTY(int, renderrate, 0) @@ -80,7 +79,6 @@ class Stats : public QQuickItem { STATS_PROPERTY(QString, packetStats, QString()) STATS_PROPERTY(QString, lodStatus, QString()) STATS_PROPERTY(QString, timingStats, QString()) - STATS_PROPERTY(QString, lodStatsRenderText, QString()) STATS_PROPERTY(int, serverElements, 0) STATS_PROPERTY(int, serverInternal, 0) STATS_PROPERTY(int, serverLeaves, 0) @@ -112,15 +110,12 @@ public: emit expandedChanged(); } } - bool getShowAcuity() { return _showAcuity; } - void setShowAcuity(bool newValue) { _showAcuity = newValue; } public slots: void forceUpdateStats() { updateStats(true); } signals: void expandedChanged(); - void showAcuityChanged(); void timingExpandedChanged(); void serverCountChanged(); void renderrateChanged(); @@ -128,7 +123,6 @@ signals: void simrateChanged(); void avatarSimrateChanged(); void avatarCountChanged(); - void lodStatsRenderTextChanged(); void packetInCountChanged(); void packetOutCountChanged(); void mbpsInChanged(); @@ -182,7 +176,6 @@ private: int _recentMaxPackets{ 0 } ; // recent max incoming voxel packets to process bool _resetRecentMaxPacketsSoon{ true }; bool _expanded{ false }; - bool _showAcuity{ false }; bool _timingExpanded{ false }; QString _monospaceFont; const AudioIOStats* _audioStats; From e4508e1d3466e5ab1c430c17d6910d71cd720d52 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Fri, 19 Feb 2016 12:06:08 -0800 Subject: [PATCH 43/72] added comment and name --- examples/audioExamples/injectorLoadTest.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/audioExamples/injectorLoadTest.js b/examples/audioExamples/injectorLoadTest.js index 59ddea6a3c..3df2d873c7 100644 --- a/examples/audioExamples/injectorLoadTest.js +++ b/examples/audioExamples/injectorLoadTest.js @@ -13,7 +13,7 @@ Script.include("../libraries/utils.js"); -var numSoundsToPlayPerBatch = 35 +var numSoundsToPlayPerBatch = 35 // Number of simultaneously playing sounds var numSoundsPlaying = 0; var timeBetweenBatch = 30000; // A green box represents an injector that is playing @@ -76,6 +76,7 @@ function playSound() { var soundBox = Entities.addEntity({ type: "Box", + name: "Debug Sound Box", color: {red: 200, green: 10, blue: 200}, dimensions: {x: 0.1, y: 0.1, z: 0.1}, position: position From 7be5811f341a34edc612ea751ead5e93a72452e4 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 19 Feb 2016 13:22:37 -0800 Subject: [PATCH 44/72] tweak to UI size, clean up screen to overlay --- interface/src/Application.cpp | 5 +-- .../src/scripting/HMDScriptingInterface.cpp | 10 ----- .../src/scripting/HMDScriptingInterface.h | 2 - interface/src/ui/ApplicationCompositor.cpp | 44 +++++-------------- interface/src/ui/ApplicationCompositor.h | 15 ++----- interface/src/ui/ApplicationOverlay.cpp | 5 ++- .../display-plugins/hmd/HmdDisplayPlugin.h | 8 +++- 7 files changed, 27 insertions(+), 62 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index dd7c524cd5..efb12c9623 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1265,8 +1265,7 @@ void Application::initializeUi() { auto displayPlugin = getActiveDisplayPlugin(); if (displayPlugin->isHmd()) { _compositor.handleRealMouseMoveEvent(false); - auto fakeScreen = _compositor.getReticlePosition(); - auto resultVec = _compositor.screenToOverlay(fakeScreen); // toGlm(pt)); + auto resultVec = _compositor.getReticlePosition(); result = QPointF(resultVec.x, resultVec.y); } return result.toPoint(); @@ -2579,7 +2578,7 @@ void Application::setLowVelocityFilter(bool lowVelocityFilter) { ivec2 Application::getMouse() { if (isHMDMode()) { - return _compositor.screenToOverlay(getTrueMouse()); + return getTrueMouse(); // FIXME } return getTrueMouse(); } diff --git a/interface/src/scripting/HMDScriptingInterface.cpp b/interface/src/scripting/HMDScriptingInterface.cpp index 1292a870c3..3f9b8ee598 100644 --- a/interface/src/scripting/HMDScriptingInterface.cpp +++ b/interface/src/scripting/HMDScriptingInterface.cpp @@ -38,16 +38,6 @@ glm::vec2 HMDScriptingInterface::overlayToSpherical(const glm::vec2 & position) return qApp->getApplicationCompositor().overlayToSpherical(position); } -glm::vec2 HMDScriptingInterface::screenToOverlay(const glm::vec2 & position) const { - return qApp->getApplicationCompositor().screenToOverlay(position); -} - -glm::vec2 HMDScriptingInterface::overlayToScreen(const glm::vec2 & position) const { - return qApp->getApplicationCompositor().overlayToScreen(position); -} - - - QScriptValue HMDScriptingInterface::getHUDLookAtPosition2D(QScriptContext* context, QScriptEngine* engine) { glm::vec3 hudIntersection; auto instance = DependencyManager::get(); diff --git a/interface/src/scripting/HMDScriptingInterface.h b/interface/src/scripting/HMDScriptingInterface.h index 1245c06575..2ead84cab1 100644 --- a/interface/src/scripting/HMDScriptingInterface.h +++ b/interface/src/scripting/HMDScriptingInterface.h @@ -32,8 +32,6 @@ public: Q_INVOKABLE glm::vec2 sphericalToOverlay(const glm::vec2 & sphericalPos) const; Q_INVOKABLE glm::vec2 overlayToSpherical(const glm::vec2 & overlayPos) const; - Q_INVOKABLE glm::vec2 screenToOverlay(const glm::vec2 & screenPos) const; - Q_INVOKABLE glm::vec2 overlayToScreen(const glm::vec2 & overlayPos) const; public: HMDScriptingInterface(); diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index a083dbf15f..5264c0261b 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -37,8 +37,11 @@ static const quint64 TOOLTIP_DELAY = 500 * MSECS_TO_USECS; static const float reticleSize = TWO_PI / 100.0f; static const float CURSOR_PIXEL_SIZE = 32.0f; -static const float MOUSE_PITCH_RANGE = 1.0f * PI; -static const float MOUSE_YAW_RANGE = 0.5f * TWO_PI; + +static const float DEFAULT_HMD_UI_ANGULAR_SIZE_IN_RADIANS = (DEFAULT_HMD_UI_ANGULAR_SIZE / 180.0f) * PI; +static const float DEFAULT_HMD_UI_HORZ_ANGULAR_SIZE_IN_RADIANS = (DEFAULT_HMD_UI_HORZ_ANGULAR_SIZE / 180.0f) * PI; +static const float MOUSE_PITCH_RANGE = DEFAULT_HMD_UI_ANGULAR_SIZE_IN_RADIANS; +static const float MOUSE_YAW_RANGE = VIRTUAL_SCREEN_SIZE_X / VIRTUAL_SCREEN_SIZE_Y * DEFAULT_HMD_UI_ANGULAR_SIZE_IN_RADIANS; static const glm::vec2 MOUSE_RANGE(MOUSE_YAW_RANGE, MOUSE_PITCH_RANGE); static gpu::BufferPointer _hemiVertices; @@ -246,7 +249,8 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int updateTooltips(); - glm::uvec2 screenSize { VIRTUAL_SCREEN_SIZE_X, VIRTUAL_SCREEN_SIZE_Y }; // = qApp->getCanvasSize(); // HMD use virtual screen size + //glm::uvec2 screenSize{ VIRTUAL_SCREEN_SIZE_X, VIRTUAL_SCREEN_SIZE_Y }; // = qApp->getCanvasSize(); // HMD use virtual screen size + glm::uvec2 screenSize = qApp->getUiSize(); // HMD use virtual screen size vec2 canvasSize = screenSize; _textureAspectRatio = aspect(canvasSize); @@ -290,7 +294,7 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int _modelTransform.getMatrix(overlayXfm); auto reticlePosition = getReticlePosition(); - glm::vec2 projection = screenToSpherical(reticlePosition); + glm::vec2 projection = overlayToSpherical(reticlePosition); //screenToSpherical(reticlePosition); float cursorDepth = getReticleDepth(); mat4 pointerXfm = glm::scale(mat4(), vec3(cursorDepth)) * glm::mat4_cast(quat(vec3(-projection.y, projection.x, 0.0f))) * glm::translate(mat4(), vec3(0, 0, -1)); mat4 reticleXfm = overlayXfm * pointerXfm; @@ -314,6 +318,7 @@ bool ApplicationCompositor::shouldCaptureMouse() const { } void ApplicationCompositor::handleLeaveEvent() { + if (shouldCaptureMouse()) { QWidget* mainWidget = (QWidget*)qApp->getWindow(); QRect mainWidgetFrame = qApp->getApplicationGeometry(); @@ -376,7 +381,8 @@ glm::vec2 ApplicationCompositor::getReticlePosition() { } void ApplicationCompositor::setReticlePosition(glm::vec2 position, bool sendFakeEvent) { if (qApp->isHMDMode()) { - _reticlePositionInHMD = glm::clamp(position, vec2(0), vec2(VIRTUAL_SCREEN_SIZE_X, VIRTUAL_SCREEN_SIZE_Y)); + glm::vec2 maxReticlePosition = qApp->getUiSize(); + _reticlePositionInHMD = glm::clamp(position, vec2(0), maxReticlePosition); if (sendFakeEvent) { // in HMD mode we need to fake our mouse moves... @@ -572,26 +578,6 @@ void ApplicationCompositor::drawSphereSection(gpu::Batch& batch) { batch.drawIndexed(gpu::TRIANGLES, _hemiIndexCount); } -glm::vec2 ApplicationCompositor::screenToSpherical(const glm::vec2& screenPos) { - glm::uvec2 screenSize { VIRTUAL_SCREEN_SIZE_X, VIRTUAL_SCREEN_SIZE_Y }; // = qApp->getCanvasSize(); - glm::vec2 result; - result.x = -(screenPos.x / screenSize.x - 0.5f); - result.y = (screenPos.y / screenSize.y - 0.5f); - result.x *= MOUSE_YAW_RANGE; - result.y *= MOUSE_PITCH_RANGE; - return result; -} - -glm::vec2 ApplicationCompositor::sphericalToScreen(const glm::vec2& sphericalPos) { - glm::uvec2 screenSize { VIRTUAL_SCREEN_SIZE_X, VIRTUAL_SCREEN_SIZE_Y }; - glm::vec2 result = sphericalPos; - result.x *= -1.0f; - result /= MOUSE_RANGE; - result += 0.5f; - result *= screenSize; - return result; -} - glm::vec2 ApplicationCompositor::sphericalToOverlay(const glm::vec2& sphericalPos) const { glm::vec2 result = sphericalPos; result.x *= -1.0f; @@ -612,14 +598,6 @@ glm::vec2 ApplicationCompositor::overlayToSpherical(const glm::vec2& overlayPos return result; } -glm::vec2 ApplicationCompositor::screenToOverlay(const glm::vec2& screenPos) const { - return sphericalToOverlay(screenToSpherical(screenPos)); -} - -glm::vec2 ApplicationCompositor::overlayToScreen(const glm::vec2& overlayPos) const { - return sphericalToScreen(overlayToSpherical(overlayPos)); -} - glm::vec2 ApplicationCompositor::overlayFromSphereSurface(const glm::vec3& sphereSurfacePoint) const { auto displayPlugin = qApp->getActiveDisplayPlugin(); diff --git a/interface/src/ui/ApplicationCompositor.h b/interface/src/ui/ApplicationCompositor.h index ff5477e30d..7523204f50 100644 --- a/interface/src/ui/ApplicationCompositor.h +++ b/interface/src/ui/ApplicationCompositor.h @@ -26,15 +26,16 @@ class PalmData; class RenderArgs; class ReticleInterface; -const int VIRTUAL_SCREEN_SIZE_X = 4096; -const int VIRTUAL_SCREEN_SIZE_Y = 2160; const float MAGNIFY_WIDTH = 220.0f; const float MAGNIFY_HEIGHT = 100.0f; const float MAGNIFY_MULT = 2.0f; -const float DEFAULT_HMD_UI_ANGULAR_SIZE = 72.0f; +const int VIRTUAL_SCREEN_SIZE_X = 3840; +const int VIRTUAL_SCREEN_SIZE_Y = 1536; +const float DEFAULT_HMD_UI_HORZ_ANGULAR_SIZE = 180.0f; +const float DEFAULT_HMD_UI_ANGULAR_SIZE = DEFAULT_HMD_UI_HORZ_ANGULAR_SIZE * (float)VIRTUAL_SCREEN_SIZE_Y / (float)VIRTUAL_SCREEN_SIZE_X; // Handles the drawing of the overlays to the screen // TODO, move divide up the rendering, displaying and input handling @@ -57,15 +58,10 @@ public: // Converter from one frame of reference to another. // Frame of reference: - // Screen: Position on the screen (x,y) // Spherical: Polar coordinates that gives the position on the sphere we project on (yaw,pitch) // Overlay: Position on the overlay (x,y) - // (x,y) in Overlay are similar than (x,y) in Screen except they can be outside of the bound of te screen. - // This allows for picking outside of the screen projection in 3D. glm::vec2 sphericalToOverlay(const glm::vec2 & sphericalPos) const; glm::vec2 overlayToSpherical(const glm::vec2 & overlayPos) const; - glm::vec2 screenToOverlay(const glm::vec2 & screenPos) const; - glm::vec2 overlayToScreen(const glm::vec2 & overlayPos) const; void computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction) const; uint32_t getOverlayTexture() const; @@ -84,9 +80,6 @@ public: float getAlpha() const { return _alpha; } void setAlpha(float alpha) { _alpha = alpha; } - static glm::vec2 screenToSpherical(const glm::vec2 & screenPos); - static glm::vec2 sphericalToScreen(const glm::vec2 & sphericalPos); - Q_INVOKABLE bool getReticleVisible() { return _reticleVisible; } Q_INVOKABLE void setReticleVisible(bool visible) { _reticleVisible = visible; } diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 636b67f83f..b654f797ec 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -251,11 +251,12 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder(RenderArgs* renderAr void ApplicationOverlay::buildFramebufferObject() { PROFILE_RANGE(__FUNCTION__); - QSize desiredSize = qApp->getDeviceSize(); + auto uiSize = qApp->getUiSize(); + QSize desiredSize (uiSize.x, uiSize.y); int currentWidth = _overlayFramebuffer ? _overlayFramebuffer->getWidth() : 0; int currentHeight = _overlayFramebuffer ? _overlayFramebuffer->getHeight() : 0; QSize frameBufferCurrentSize(currentWidth, currentHeight); - + if (_overlayFramebuffer && desiredSize == frameBufferCurrentSize) { // Already built return; diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h index a504752a6f..9ec40e02a8 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h @@ -18,7 +18,13 @@ public: glm::mat4 getEyeToHeadTransform(Eye eye) const override final { return _eyeOffsets[eye]; } glm::mat4 getEyeProjection(Eye eye, const glm::mat4& baseProjection) const override final { return _eyeProjections[eye]; } glm::mat4 getCullingProjection(const glm::mat4& baseProjection) const override final { return _cullingProjection; } - glm::uvec2 getRecommendedUiSize() const override final { return uvec2(1920, 1080); } + glm::uvec2 getRecommendedUiSize() const override final { + // FIXME - would be good to have these values sync with ApplicationCompositor in a better way. + const int VIRTUAL_SCREEN_SIZE_X = 3840; + const int VIRTUAL_SCREEN_SIZE_Y = 1536; + auto result = uvec2(VIRTUAL_SCREEN_SIZE_X, VIRTUAL_SCREEN_SIZE_Y); + return result; + } glm::uvec2 getRecommendedRenderSize() const override final { return _renderTargetSize; } void activate() override; void deactivate() override; From d9aa5d8857f55d895c3689811e31ec9cb6c856e9 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 19 Feb 2016 13:25:53 -0800 Subject: [PATCH 45/72] cleanup dead code --- interface/src/ui/ApplicationCompositor.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 5264c0261b..6c073be175 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -249,7 +249,6 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int updateTooltips(); - //glm::uvec2 screenSize{ VIRTUAL_SCREEN_SIZE_X, VIRTUAL_SCREEN_SIZE_Y }; // = qApp->getCanvasSize(); // HMD use virtual screen size glm::uvec2 screenSize = qApp->getUiSize(); // HMD use virtual screen size vec2 canvasSize = screenSize; _textureAspectRatio = aspect(canvasSize); @@ -294,7 +293,7 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int _modelTransform.getMatrix(overlayXfm); auto reticlePosition = getReticlePosition(); - glm::vec2 projection = overlayToSpherical(reticlePosition); //screenToSpherical(reticlePosition); + glm::vec2 projection = overlayToSpherical(reticlePosition); float cursorDepth = getReticleDepth(); mat4 pointerXfm = glm::scale(mat4(), vec3(cursorDepth)) * glm::mat4_cast(quat(vec3(-projection.y, projection.x, 0.0f))) * glm::translate(mat4(), vec3(0, 0, -1)); mat4 reticleXfm = overlayXfm * pointerXfm; From e21d9042d06cadf7c50a9d55ed659664aef23492 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Fri, 19 Feb 2016 13:34:06 -0800 Subject: [PATCH 46/72] Remove some logging. --- libraries/audio-client/src/AudioClient.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index da62645fec..01ceb73941 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -1154,9 +1154,6 @@ qint64 AudioClient::AudioOutputIODevice::readData(char * data, qint64 maxSize) { if (!bytesAudioOutputUnplayed) { qCDebug(audioclient) << "empty audio buffer"; } - if (!bytesWritten) { - qCDebug(audioclient) << "no audio written" << _audio->_audioOutput->bytesFree() << "free," << _audio->_audioOutput->bufferSize() << "buffer"; - } if (bytesAudioOutputUnplayed == 0 && bytesWritten == 0) { _unfulfilledReads++; } From 66e8f070e42c37bc39750326cdf9bc4f4cd1f550 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Fri, 19 Feb 2016 13:48:54 -0800 Subject: [PATCH 47/72] popup windows --- interface/resources/qml/Browser.qml | 12 ++++++------ interface/resources/qml/controls/WebView.qml | 17 +++++++++++++---- interface/resources/qml/hifi/Desktop.qml | 10 ++++++++-- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml index 382acc237c..89ab333a0d 100644 --- a/interface/resources/qml/Browser.qml +++ b/interface/resources/qml/Browser.qml @@ -14,7 +14,8 @@ Window { destroyOnInvisible: true width: 800 height: 600 - + property alias webView: webview + Component.onCompleted: { visible = true addressBar.text = webview.url @@ -28,6 +29,7 @@ Window { } Item { + id:item anchors.fill: parent Rectangle { anchors.left: parent.left @@ -125,12 +127,10 @@ Window { console.log("New icon: " + icon) } - profile: WebEngineProfile { - id: webviewProfile - storageName: "qmlUserBrowser" - } - + profile: desktop.browserProfile + } + } // item Keys.onPressed: { diff --git a/interface/resources/qml/controls/WebView.qml b/interface/resources/qml/controls/WebView.qml index c7ae322cba..90454d48c2 100644 --- a/interface/resources/qml/controls/WebView.qml +++ b/interface/resources/qml/controls/WebView.qml @@ -11,6 +11,7 @@ WebEngineView { root.javaScriptConsoleMessage.connect(function(level, message, lineNumber, sourceID) { console.log("Web Window JS message: " + sourceID + " " + lineNumber + " " + message); }); + } // FIXME hack to get the URL with the auth token included. Remove when we move to Qt 5.6 @@ -36,6 +37,11 @@ WebEngineView { } } + onFeaturePermissionRequested: { + console.log('permission requested',securityOrigin, feature) + grantFeaturePermission(securityOrigin, feature, true); + } + onLoadingChanged: { // Required to support clicking on "hifi://" links if (WebEngineView.LoadStartedStatus == loadRequest.status) { @@ -48,9 +54,12 @@ WebEngineView { } } - profile: WebEngineProfile { - id: webviewProfile - httpUserAgent: "Mozilla/5.0 (HighFidelityInterface)" - storageName: "qmlWebEngine" + onNewViewRequested:{ + var component = Qt.createComponent("../Browser.qml"); + var newWindow = component.createObject(desktop); + request.openIn(newWindow.webView) } + + + profile: desktop.browserProfile } diff --git a/interface/resources/qml/hifi/Desktop.qml b/interface/resources/qml/hifi/Desktop.qml index 5951101194..25eabcb158 100644 --- a/interface/resources/qml/hifi/Desktop.qml +++ b/interface/resources/qml/hifi/Desktop.qml @@ -9,8 +9,8 @@ Desktop { id: desktop Component.onCompleted: { - WebEngine.settings.javascriptCanOpenWindows = false; - WebEngine.settings.javascriptCanAccessClipboard = false; + WebEngine.settings.javascriptCanOpenWindows = true; + WebEngine.settings.javascriptCanAccessClipboard = true; WebEngine.settings.spatialNavigationEnabled = true; WebEngine.settings.localContentCanAccessRemoteUrls = true; } @@ -18,6 +18,12 @@ Desktop { // The tool window, one instance property alias toolWindow: toolWindow ToolWindow { id: toolWindow } + + property var browserProfile: WebEngineProfile { + id: webviewProfile + httpUserAgent: "Chrome/48.0 (HighFidelityInterface)" + storageName: "qmlWebEngine" + } Action { text: "Open Browser" From afb6f1fe840b90d02fc22a3f2f175bf4b3b9ae0c Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Fri, 19 Feb 2016 13:50:30 -0800 Subject: [PATCH 48/72] no clipboard --- interface/resources/qml/hifi/Desktop.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/Desktop.qml b/interface/resources/qml/hifi/Desktop.qml index 25eabcb158..5227d3cb2e 100644 --- a/interface/resources/qml/hifi/Desktop.qml +++ b/interface/resources/qml/hifi/Desktop.qml @@ -10,7 +10,7 @@ Desktop { Component.onCompleted: { WebEngine.settings.javascriptCanOpenWindows = true; - WebEngine.settings.javascriptCanAccessClipboard = true; + WebEngine.settings.javascriptCanAccessClipboard = false; WebEngine.settings.spatialNavigationEnabled = true; WebEngine.settings.localContentCanAccessRemoteUrls = true; } @@ -18,7 +18,7 @@ Desktop { // The tool window, one instance property alias toolWindow: toolWindow ToolWindow { id: toolWindow } - + property var browserProfile: WebEngineProfile { id: webviewProfile httpUserAgent: "Chrome/48.0 (HighFidelityInterface)" From 7ec09c49f3d8f34989c0945409ea19b89f9f6cd8 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Fri, 19 Feb 2016 13:53:22 -0800 Subject: [PATCH 49/72] feature request is in another pull --- interface/resources/qml/controls/WebView.qml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/interface/resources/qml/controls/WebView.qml b/interface/resources/qml/controls/WebView.qml index 90454d48c2..bb74e6a07d 100644 --- a/interface/resources/qml/controls/WebView.qml +++ b/interface/resources/qml/controls/WebView.qml @@ -37,11 +37,6 @@ WebEngineView { } } - onFeaturePermissionRequested: { - console.log('permission requested',securityOrigin, feature) - grantFeaturePermission(securityOrigin, feature, true); - } - onLoadingChanged: { // Required to support clicking on "hifi://" links if (WebEngineView.LoadStartedStatus == loadRequest.status) { From 56f8282607619d5a5125323d4a9b715b99547603 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Fri, 19 Feb 2016 13:54:31 -0800 Subject: [PATCH 50/72] dont need this code here --- interface/resources/qml/Browser.qml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml index 110011d2c0..382acc237c 100644 --- a/interface/resources/qml/Browser.qml +++ b/interface/resources/qml/Browser.qml @@ -129,10 +129,6 @@ Window { id: webviewProfile storageName: "qmlUserBrowser" } - - onFeaturePermissionRequested: { - grantFeaturePermission(securityOrigin, feature, true); - } } } // item From 9f7feed544e76d60a60f045d08a28abdcca93a69 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Fri, 19 Feb 2016 14:00:22 -0800 Subject: [PATCH 51/72] Remove LOD PID controller. --- interface/src/LODManager.cpp | 45 ------------------------------------ interface/src/LODManager.h | 15 ------------ 2 files changed, 60 deletions(-) diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index 2644e55bfb..80f96f7435 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -25,24 +25,8 @@ Setting::Handle hmdLODDecreaseFPS("hmdLODDecreaseFPS", DEFAULT_HMD_LOD_DO // acuity: a pseudo-acuity target is held, or adjusted to match minimum frame rates (and a PID controlls avatar rendering distance) // If unspecified, acuity is used only if user has specified non-default minumum frame rates. Setting::Handle lodPreference("lodPreference", (int)LODManager::LODPreference::acuity); -const float SMALLEST_REASONABLE_HORIZON = 50.0f; // meters -Setting::Handle renderDistanceInverseHighLimit("renderDistanceInverseHighLimit", 1.0f / SMALLEST_REASONABLE_HORIZON); -void LODManager::setRenderDistanceInverseHighLimit(float newValue) { - renderDistanceInverseHighLimit.set(newValue); // persist it, and tell all the controllers that use it - _renderDistanceController.setControlledValueHighLimit(newValue); -} LODManager::LODManager() { - - setRenderDistanceInverseHighLimit(renderDistanceInverseHighLimit.get()); - setRenderDistanceInverseLowLimit(1.0f / (float)TREE_SCALE); - // Advice for tuning parameters: - // See PIDController.h. There's a section on tuning in the reference. - // Turn on logging with the following (or from js with LODManager.setRenderDistanceControllerHistory("render pid", 240)) - //setRenderDistanceControllerHistory("render pid", 60 * 4); - // Note that extra logging/hysteresis is turned off in Avatar.cpp when the above logging is on. - setRenderDistanceKP(0.000012f); // Usually about 0.6 of largest that doesn't oscillate when other parameters 0. - setRenderDistanceKI(0.00002f); // Big enough to bring us to target with the above KP. } float LODManager::getLODDecreaseFPS() { @@ -234,35 +218,6 @@ QString LODManager::getLODFeedbackText() { return result; } -static float renderDistance = (float)TREE_SCALE; -static int renderedCount = 0; -static int lastRenderedCount = 0; -float LODManager::getRenderDistance() { - return renderDistance; -} -int LODManager::getRenderedCount() { - return lastRenderedCount; -} -// compare autoAdjustLOD() -void LODManager::updatePIDRenderDistance(float targetFps, float measuredFps, float deltaTime, bool isThrottled) { - float distance; - if (!isThrottled) { - _renderDistanceController.setMeasuredValueSetpoint(targetFps); // No problem updating in flight. - // The PID controller raises the controlled value when the measured value goes up. - // The measured value is frame rate. When the controlled value (1 / render cutoff distance) - // goes up, the render cutoff distance gets closer, the number of rendered avatars is less, and frame rate - // goes up. - distance = 1.0f / _renderDistanceController.update(measuredFps, deltaTime); - } else { - // Here we choose to just use the maximum render cutoff distance if throttled. - distance = 1.0f / _renderDistanceController.getControlledValueLowLimit(); - } - _renderDistanceAverage.updateAverage(distance); - renderDistance = _renderDistanceAverage.getAverage(); // average only once per cycle - lastRenderedCount = renderedCount; - renderedCount = 0; -} - bool LODManager::shouldRender(const RenderArgs* args, const AABox& bounds) { // FIXME - eventually we want to use the render accuracy as an indicator for the level of detail // to use in rendering. diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h index a9fabe8799..16a1098505 100644 --- a/interface/src/LODManager.h +++ b/interface/src/LODManager.h @@ -81,18 +81,6 @@ public: acuity, unspecified }; - Q_INVOKABLE void setRenderDistanceKP(float newValue) { _renderDistanceController.setKP(newValue); } - Q_INVOKABLE void setRenderDistanceKI(float newValue) { _renderDistanceController.setKI(newValue); } - Q_INVOKABLE void setRenderDistanceKD(float newValue) { _renderDistanceController.setKD(newValue); } - Q_INVOKABLE bool getRenderDistanceControllerIsLogging() { return _renderDistanceController.getIsLogging(); } - Q_INVOKABLE void setRenderDistanceControllerHistory(QString label, int size) { return _renderDistanceController.setHistorySize(label, size); } - Q_INVOKABLE float getRenderDistanceInverseLowLimit() { return _renderDistanceController.getControlledValueLowLimit(); } - Q_INVOKABLE void setRenderDistanceInverseLowLimit(float newValue) { _renderDistanceController.setControlledValueLowLimit(newValue); } - Q_INVOKABLE float getRenderDistanceInverseHighLimit() { return _renderDistanceController.getControlledValueHighLimit(); } - Q_INVOKABLE void setRenderDistanceInverseHighLimit(float newValue); - void updatePIDRenderDistance(float targetFps, float measuredFps, float deltaTime, bool isThrottled); - float getRenderDistance(); - int getRenderedCount(); static bool shouldRender(const RenderArgs* args, const AABox& bounds); void autoAdjustLOD(float currentFPS); @@ -123,9 +111,6 @@ private: SimpleMovingAverage _fpsAverageStartWindow = START_DELAY_SAMPLES_OF_FRAMES; SimpleMovingAverage _fpsAverageDownWindow = DOWN_SHIFT_SAMPLES_OF_FRAMES; SimpleMovingAverage _fpsAverageUpWindow = UP_SHIFT_SAMPLES_OF_FRAMES; - - PIDController _renderDistanceController{}; - SimpleMovingAverage _renderDistanceAverage{ 10 }; }; #endif // hifi_LODManager_h From 00f3d6e382f9c9b8dbd9fc3439ebba05f8002a77 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Fri, 19 Feb 2016 14:05:21 -0800 Subject: [PATCH 52/72] Remove LODPreference enum. --- interface/src/LODManager.cpp | 5 ----- interface/src/LODManager.h | 6 ------ 2 files changed, 11 deletions(-) diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index 80f96f7435..64b506059c 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -20,11 +20,6 @@ Setting::Handle desktopLODDecreaseFPS("desktopLODDecreaseFPS", DEFAULT_DESKTOP_LOD_DOWN_FPS); Setting::Handle hmdLODDecreaseFPS("hmdLODDecreaseFPS", DEFAULT_HMD_LOD_DOWN_FPS); -// There are two different systems in use, based on lodPreference: -// pid: renderDistance is adjusted by a PID such that frame rate targets are met. -// acuity: a pseudo-acuity target is held, or adjusted to match minimum frame rates (and a PID controlls avatar rendering distance) -// If unspecified, acuity is used only if user has specified non-default minumum frame rates. -Setting::Handle lodPreference("lodPreference", (int)LODManager::LODPreference::acuity); LODManager::LODManager() { } diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h index 16a1098505..585ac73105 100644 --- a/interface/src/LODManager.h +++ b/interface/src/LODManager.h @@ -76,12 +76,6 @@ public: Q_INVOKABLE float getLODDecreaseFPS(); Q_INVOKABLE float getLODIncreaseFPS(); - enum class LODPreference { - pid = 0, - acuity, - unspecified - }; - static bool shouldRender(const RenderArgs* args, const AABox& bounds); void autoAdjustLOD(float currentFPS); From 7219a925d2697744ba28713caa4970b6dd4f86cb Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 19 Feb 2016 14:17:28 -0800 Subject: [PATCH 53/72] remove getTrueMouse() --- interface/src/Application.cpp | 25 +++++++++++-------------- interface/src/Application.h | 2 -- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index efb12c9623..792a06e136 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2064,9 +2064,10 @@ void Application::keyPressEvent(QKeyEvent* event) { break; case Qt::Key_Space: { if (!event->isAutoRepeat()) { + // FIXME -- I don't think we've tested the HFActionEvent in a while... this looks possibly dubious // this starts an HFActionEvent HFActionEvent startActionEvent(HFActionEvent::startType(), - computePickRay(getTrueMouse().x, getTrueMouse().y)); + computePickRay(getMouse().x, getMouse().y)); sendEvent(this, &startActionEvent); } @@ -2115,9 +2116,10 @@ void Application::keyReleaseEvent(QKeyEvent* event) { switch (event->key()) { case Qt::Key_Space: { if (!event->isAutoRepeat()) { + // FIXME -- I don't think we've tested the HFActionEvent in a while... this looks possibly dubious // this ends the HFActionEvent HFActionEvent endActionEvent(HFActionEvent::endType(), - computePickRay(getTrueMouse().x, getTrueMouse().y)); + computePickRay(getMouse().x, getMouse().y)); sendEvent(this, &endActionEvent); } break; @@ -2577,10 +2579,15 @@ void Application::setLowVelocityFilter(bool lowVelocityFilter) { } ivec2 Application::getMouse() { + auto reticlePosition = _compositor.getReticlePosition(); + + // in the HMD, the reticlePosition is the mouse position if (isHMDMode()) { - return getTrueMouse(); // FIXME + return reticlePosition; } - return getTrueMouse(); + + // in desktop mode, we need to map from global to widget space + return toGlm(_glWidget->mapFromGlobal(QPoint(reticlePosition.x, reticlePosition.y))); } FaceTracker* Application::getActiveFaceTracker() { @@ -4738,20 +4745,10 @@ QSize Application::getDeviceSize() const { return fromGlm(getActiveDisplayPlugin()->getRecommendedRenderSize()); } -PickRay Application::computePickRay() { - return computePickRay(getTrueMouse().x, getTrueMouse().y); -} - bool Application::isThrottleRendering() const { return getActiveDisplayPlugin()->isThrottled(); } -// FIXME -- consolidate users of getTrueMouse() _compositor.getReticlePosition() -ivec2 Application::getTrueMouse() { - auto reticlePosition = _compositor.getReticlePosition(); - return toGlm(_glWidget->mapFromGlobal(QPoint(reticlePosition.x, reticlePosition.y))); -} - bool Application::hasFocus() const { return getActiveDisplayPlugin()->hasFocus(); } diff --git a/interface/src/Application.h b/interface/src/Application.h index f05c5c6123..482f0afef6 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -119,7 +119,6 @@ public: glm::uvec2 getUiSize() const; QSize getDeviceSize() const; bool hasFocus() const; - PickRay computePickRay(); bool isThrottleRendering() const; @@ -142,7 +141,6 @@ public: EntityEditPacketSender* getEntityEditPacketSender() { return &_entityEditSender; } ivec2 getMouse(); - ivec2 getTrueMouse(); FaceTracker* getActiveFaceTracker(); FaceTracker* getSelectedFaceTracker(); From a22b25aad9ed395de12c83340ac339791a99e80f Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Fri, 19 Feb 2016 14:37:58 -0800 Subject: [PATCH 54/72] Make defaults match our performance statements. (Half of present rate.) --- interface/src/LODManager.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h index 585ac73105..ef4d9c8e62 100644 --- a/interface/src/LODManager.h +++ b/interface/src/LODManager.h @@ -18,8 +18,8 @@ #include #include -const float DEFAULT_DESKTOP_LOD_DOWN_FPS = 15.0; -const float DEFAULT_HMD_LOD_DOWN_FPS = 30.0; +const float DEFAULT_DESKTOP_LOD_DOWN_FPS = 30.0; +const float DEFAULT_HMD_LOD_DOWN_FPS = 45.0; const float MAX_LIKELY_DESKTOP_FPS = 59.0; // this is essentially, V-synch - 1 fps const float MAX_LIKELY_HMD_FPS = 74.0; // this is essentially, V-synch - 1 fps const float INCREASE_LOD_GAP = 15.0f; From b94410a32311b4ca2e6eeae00175dbcc9fe4b087 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 19 Feb 2016 14:39:46 -0800 Subject: [PATCH 55/72] MyAvatar: fix for turning with arrow keys on start up --- interface/src/avatar/MyAvatar.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 98d25a64c8..8c84299e08 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -421,8 +421,8 @@ private: AtRestDetector _hmdAtRestDetector; bool _lastIsMoving { false }; bool _hoverReferenceCameraFacingIsCaptured { false }; - glm::vec3 _hoverReferenceCameraFacing; // hmd sensor space - + glm::vec3 _hoverReferenceCameraFacing { 0.0f, 0.0f, -1.0f }; // hmd sensor space + float AVATAR_MOVEMENT_ENERGY_CONSTANT { 0.001f }; float AUDIO_ENERGY_CONSTANT { 0.000001f }; float MAX_AVATAR_MOVEMENT_PER_FRAME { 30.0f }; From 13c602e2a36cf7a31771b712f42e18d27cc1aef8 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Fri, 19 Feb 2016 15:12:44 -0800 Subject: [PATCH 56/72] Remove mumbleUnsynchronizedFPS, which is obsolete now that the update/render rate is not in power-of-two lockstep with present rate, and which had users other than the LOD PID. --- interface/src/Application.cpp | 6 ------ interface/src/Application.h | 2 -- 2 files changed, 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0d9fde5176..a752ee305f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1635,13 +1635,7 @@ void Application::paintGL() { }); } - // Some LOD-like controls need to know a smoothly varying "potential" frame rate that doesn't - // include time waiting for sync, and which can report a number above target if we've got the headroom. - // In my tests, the following is mostly less than 0.5ms, and never more than 3ms. I don't think its worth measuring during runtime. - const float paintWaitAndQTTimerAllowance = 0.001f; // seconds - // Store both values now for use by next cycle. _lastInstantaneousFps = instantaneousFps; - _lastUnsynchronizedFps = 1.0f / (((usecTimestampNow() - now) / (float)USECS_PER_SECOND) + paintWaitAndQTTimerAllowance); _pendingPaint = false; } diff --git a/interface/src/Application.h b/interface/src/Application.h index d5b677302a..2db075b508 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -157,7 +157,6 @@ public: float getFps() const { return _fps; } float getTargetFrameRate(); // frames/second float getLastInstanteousFps() const { return _lastInstantaneousFps; } - float getLastUnsynchronizedFps() const { return _lastUnsynchronizedFps; } float getFieldOfView() { return _fieldOfView.get(); } void setFieldOfView(float fov); @@ -402,7 +401,6 @@ private: QElapsedTimer _timerStart; QElapsedTimer _lastTimeUpdated; float _lastInstantaneousFps { 0.0f }; - float _lastUnsynchronizedFps { 0.0f }; ShapeManager _shapeManager; PhysicalEntitySimulation _entitySimulation; From 64ec56bf892efa85d3c1cb83db9a0fd95547275f Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 19 Feb 2016 15:36:51 -0800 Subject: [PATCH 57/72] Guards and warnings in QML rendering --- libraries/gl/src/gl/OffscreenQmlSurface.cpp | 14 ++++++++++---- libraries/gl/src/gl/OffscreenQmlSurface.h | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index 42eea08057..e22feb694d 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -175,6 +175,7 @@ private: doneCurrent(); getContextObject()->moveToThread(QCoreApplication::instance()->thread()); + _thread.quit(); _cond.wakeOne(); } @@ -228,7 +229,7 @@ private: _quickWindow->setRenderTarget(GetName(*_fbo), QSize(_size.x, _size.y)); - { + try { PROFILE_RANGE("qml_render") TexturePtr texture = _textures.getNextTexture(); _fbo->Bind(Framebuffer::Target::Draw); @@ -245,8 +246,10 @@ private: DefaultFramebuffer().Bind(Framebuffer::Target::Draw); _quickWindow->resetOpenGLState(); _escrow.submit(GetName(*texture)); + _lastRenderTime = usecTimestampNow(); + } catch (std::runtime_error& error) { + qWarning() << "Failed to render QML " << error.what(); } - _lastRenderTime = usecTimestampNow(); } void aboutToQuit() { @@ -321,7 +324,7 @@ OffscreenQmlSurface::~OffscreenQmlSurface() { void OffscreenQmlSurface::create(QOpenGLContext* shareContext) { _renderer = new OffscreenQmlRenderer(this, shareContext); - + _renderer->_renderControl->_renderWindow = _proxyWindow; // Create a QML engine. _qmlEngine = new QQmlEngine; if (!_qmlEngine->incubationController()) { @@ -610,7 +613,10 @@ bool OffscreenQmlSurface::isPaused() const { } void OffscreenQmlSurface::setProxyWindow(QWindow* window) { - _renderer->_renderControl->_renderWindow = window; + _proxyWindow = window; + if (_renderer && _renderer->_renderControl) { + _renderer->_renderControl->_renderWindow = window; + } } QObject* OffscreenQmlSurface::getEventHandler() { diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.h b/libraries/gl/src/gl/OffscreenQmlSurface.h index 9e3ee06f92..5641d16a30 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.h +++ b/libraries/gl/src/gl/OffscreenQmlSurface.h @@ -95,7 +95,7 @@ private: bool _paused{ true }; uint8_t _maxFps{ 60 }; MouseTranslator _mouseTranslator{ [](const QPointF& p) { return p.toPoint(); } }; - + QWindow* _proxyWindow { nullptr }; }; #endif From 021b86c3fe0d3497f26ba898e60ba1e6890d5163 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 19 Feb 2016 15:41:40 -0800 Subject: [PATCH 58/72] Cap the max concurrent webviews, and deallocate unrendered views after 30 seconds --- .../src/RenderableWebEntityItem.cpp | 274 ++++++++++-------- .../src/RenderableWebEntityItem.h | 8 + 2 files changed, 164 insertions(+), 118 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index ce89197069..ade44f94a0 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -28,6 +28,11 @@ const float DPI = 30.47f; const float METERS_TO_INCHES = 39.3701f; +static uint32_t _currentWebCount { 0 }; +// Don't allow more than 100 concurrent web views +static const uint32_t MAX_CONCURRENT_WEB_VIEWS = 100; +// If a web-view hasn't been rendered for 30 seconds, de-allocate the framebuffer +static uint64_t MAX_NO_RENDER_INTERVAL = 30 * USECS_PER_SECOND; EntityItemPointer RenderableWebEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { EntityItemPointer entity{ new RenderableWebEntityItem(entityID) }; @@ -41,28 +46,120 @@ RenderableWebEntityItem::RenderableWebEntityItem(const EntityItemID& entityItemI } RenderableWebEntityItem::~RenderableWebEntityItem() { - if (_webSurface) { - _webSurface->pause(); - _webSurface->disconnect(_connection); - // The lifetime of the QML surface MUST be managed by the main thread - // Additionally, we MUST use local variables copied by value, rather than - // member variables, since they would implicitly refer to a this that - // is no longer valid - auto webSurface = _webSurface; - AbstractViewStateInterface::instance()->postLambdaEvent([webSurface] { - webSurface->deleteLater(); - }); - } - - QObject::disconnect(_mousePressConnection); - QObject::disconnect(_mouseReleaseConnection); - QObject::disconnect(_mouseMoveConnection); - QObject::disconnect(_hoverLeaveConnection); + destroyWebSurface(); qDebug() << "Destroyed web entity " << getID(); } +bool RenderableWebEntityItem::buildWebSurface(EntityTreeRenderer* renderer) { + if (_currentWebCount >= MAX_CONCURRENT_WEB_VIEWS) { + qWarning() << "Too many concurrent web views to create new view"; + return false; + } + + qDebug() << "Building web surface"; + ++_currentWebCount; + QOpenGLContext * currentContext = QOpenGLContext::currentContext(); + _webSurface = new OffscreenQmlSurface(); + _webSurface->create(currentContext); + _webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/")); + _webSurface->load("WebEntity.qml"); + _webSurface->resume(); + _webSurface->getRootItem()->setProperty("url", _sourceUrl); + _connection = QObject::connect(_webSurface, &OffscreenQmlSurface::textureUpdated, [&](GLuint textureId) { + _texture = textureId; + }); + + auto forwardMouseEvent = [=](const RayToEntityIntersectionResult& intersection, const QMouseEvent* event, unsigned int deviceId) { + // Ignore mouse interaction if we're locked + if (this->getLocked()) { + return; + } + + if (event->button() == Qt::MouseButton::RightButton) { + if (event->type() == QEvent::MouseButtonPress) { + const QMouseEvent* mouseEvent = static_cast(event); + _lastPress = toGlm(mouseEvent->pos()); + } + } + + if (intersection.entityID == getID()) { + if (event->button() == Qt::MouseButton::RightButton) { + if (event->type() == QEvent::MouseButtonRelease) { + const QMouseEvent* mouseEvent = static_cast(event); + ivec2 dist = glm::abs(toGlm(mouseEvent->pos()) - _lastPress); + if (!glm::any(glm::greaterThan(dist, ivec2(1)))) { + AbstractViewStateInterface::instance()->postLambdaEvent([this] { + QMetaObject::invokeMethod(_webSurface->getRootItem(), "goBack"); + }); + } + _lastPress = ivec2(INT_MIN); + } + return; + } + + // FIXME doesn't work... double click events not received + if (event->type() == QEvent::MouseButtonDblClick) { + AbstractViewStateInterface::instance()->postLambdaEvent([this] { + _webSurface->getRootItem()->setProperty("url", _sourceUrl); + }); + } + + if (event->button() == Qt::MouseButton::MiddleButton) { + if (event->type() == QEvent::MouseButtonRelease) { + AbstractViewStateInterface::instance()->postLambdaEvent([this] { + _webSurface->getRootItem()->setProperty("url", _sourceUrl); + }); + } + return; + } + + // Map the intersection point to an actual offscreen pixel + glm::vec3 point = intersection.intersection; + point -= getPosition(); + point = glm::inverse(getRotation()) * point; + point /= getDimensions(); + point += 0.5f; + point.y = 1.0f - point.y; + point *= getDimensions() * METERS_TO_INCHES * DPI; + + if (event->button() == Qt::MouseButton::LeftButton) { + if (event->type() == QEvent::MouseButtonPress) { + this->_pressed = true; + this->_lastMove = ivec2((int)point.x, (int)point.y); + } else if (event->type() == QEvent::MouseButtonRelease) { + this->_pressed = false; + } + } + if (event->type() == QEvent::MouseMove) { + this->_lastMove = ivec2((int)point.x, (int)point.y); + } + + // Forward the mouse event. + QMouseEvent mappedEvent(event->type(), + QPoint((int)point.x, (int)point.y), + event->screenPos(), event->button(), + event->buttons(), event->modifiers()); + QCoreApplication::sendEvent(_webSurface->getWindow(), &mappedEvent); + } + }; + + _mousePressConnection = QObject::connect(renderer, &EntityTreeRenderer::mousePressOnEntity, forwardMouseEvent); + _mouseReleaseConnection = QObject::connect(renderer, &EntityTreeRenderer::mouseReleaseOnEntity, forwardMouseEvent); + _mouseMoveConnection = QObject::connect(renderer, &EntityTreeRenderer::mouseMoveOnEntity, forwardMouseEvent); + _hoverLeaveConnection = QObject::connect(renderer, &EntityTreeRenderer::hoverLeaveEntity, [=](const EntityItemID& entityItemID, const MouseEvent& event) { + if (this->_pressed && this->getID() == entityItemID) { + // If the user mouses off the entity while the button is down, simulate a mouse release + QMouseEvent mappedEvent(QEvent::MouseButtonRelease, + QPoint(_lastMove.x, _lastMove.y), + Qt::MouseButton::LeftButton, + Qt::MouseButtons(), Qt::KeyboardModifiers()); + QCoreApplication::sendEvent(_webSurface->getWindow(), &mappedEvent); + } + }); + return true; +} + void RenderableWebEntityItem::render(RenderArgs* args) { - #ifdef WANT_EXTRA_DEBUGGING { gpu::Batch& batch = *args->_batch; @@ -72,108 +169,15 @@ void RenderableWebEntityItem::render(RenderArgs* args) { } #endif + if (!_webSurface) { + if (!buildWebSurface(static_cast(args->_renderer))) { + return; + } + } + + _lastRenderTime = usecTimestampNow(); QOpenGLContext * currentContext = QOpenGLContext::currentContext(); QSurface * currentSurface = currentContext->surface(); - if (!_webSurface) { - _webSurface = new OffscreenQmlSurface(); - _webSurface->create(currentContext); - _webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/")); - _webSurface->load("WebEntity.qml"); - _webSurface->resume(); - _webSurface->getRootItem()->setProperty("url", _sourceUrl); - _connection = QObject::connect(_webSurface, &OffscreenQmlSurface::textureUpdated, [&](GLuint textureId) { - _texture = textureId; - }); - - auto forwardMouseEvent = [=](const RayToEntityIntersectionResult& intersection, const QMouseEvent* event, unsigned int deviceId) { - // Ignore mouse interaction if we're locked - if (this->getLocked()) { - return; - } - - if (event->button() == Qt::MouseButton::RightButton) { - if (event->type() == QEvent::MouseButtonPress) { - const QMouseEvent* mouseEvent = static_cast(event); - _lastPress = toGlm(mouseEvent->pos()); - } - } - - if (intersection.entityID == getID()) { - if (event->button() == Qt::MouseButton::RightButton) { - if (event->type() == QEvent::MouseButtonRelease) { - const QMouseEvent* mouseEvent = static_cast(event); - ivec2 dist = glm::abs(toGlm(mouseEvent->pos()) - _lastPress); - if (!glm::any(glm::greaterThan(dist, ivec2(1)))) { - AbstractViewStateInterface::instance()->postLambdaEvent([this] { - QMetaObject::invokeMethod(_webSurface->getRootItem(), "goBack"); - }); - } - _lastPress = ivec2(INT_MIN); - } - return; - } - - // FIXME doesn't work... double click events not received - if (event->type() == QEvent::MouseButtonDblClick) { - AbstractViewStateInterface::instance()->postLambdaEvent([this] { - _webSurface->getRootItem()->setProperty("url", _sourceUrl); - }); - } - - if (event->button() == Qt::MouseButton::MiddleButton) { - if (event->type() == QEvent::MouseButtonRelease) { - AbstractViewStateInterface::instance()->postLambdaEvent([this] { - _webSurface->getRootItem()->setProperty("url", _sourceUrl); - }); - } - return; - } - - // Map the intersection point to an actual offscreen pixel - glm::vec3 point = intersection.intersection; - point -= getPosition(); - point = glm::inverse(getRotation()) * point; - point /= getDimensions(); - point += 0.5f; - point.y = 1.0f - point.y; - point *= getDimensions() * METERS_TO_INCHES * DPI; - - if (event->button() == Qt::MouseButton::LeftButton) { - if (event->type() == QEvent::MouseButtonPress) { - this->_pressed = true; - this->_lastMove = ivec2((int)point.x, (int)point.y); - } else if (event->type() == QEvent::MouseButtonRelease) { - this->_pressed = false; - } - } - if (event->type() == QEvent::MouseMove) { - this->_lastMove = ivec2((int)point.x, (int)point.y); - } - - // Forward the mouse event. - QMouseEvent mappedEvent(event->type(), - QPoint((int)point.x, (int)point.y), - event->screenPos(), event->button(), - event->buttons(), event->modifiers()); - QCoreApplication::sendEvent(_webSurface->getWindow(), &mappedEvent); - } - }; - - EntityTreeRenderer* renderer = static_cast(args->_renderer); - _mousePressConnection = QObject::connect(renderer, &EntityTreeRenderer::mousePressOnEntity, forwardMouseEvent); - _mouseReleaseConnection = QObject::connect(renderer, &EntityTreeRenderer::mouseReleaseOnEntity, forwardMouseEvent); - _mouseMoveConnection = QObject::connect(renderer, &EntityTreeRenderer::mouseMoveOnEntity, forwardMouseEvent); - _hoverLeaveConnection = QObject::connect(renderer, &EntityTreeRenderer::hoverLeaveEntity, [=](const EntityItemID& entityItemID, const MouseEvent& event) { - if (this->_pressed && this->getID() == entityItemID) { - // If the user mouses off the entity while the button is down, simulate a mouse release - QMouseEvent mappedEvent(QEvent::MouseButtonRelease, - QPoint(_lastMove.x, _lastMove.y), - Qt::MouseButton::LeftButton, - Qt::MouseButtons(), Qt::KeyboardModifiers()); - QCoreApplication::sendEvent(_webSurface->getWindow(), &mappedEvent); - } - }); - } glm::vec2 dims = glm::vec2(getDimensions()); dims *= METERS_TO_INCHES * DPI; @@ -223,3 +227,37 @@ void RenderableWebEntityItem::setProxyWindow(QWindow* proxyWindow) { QObject* RenderableWebEntityItem::getEventHandler() { return _webSurface->getEventHandler(); } + +void RenderableWebEntityItem::destroyWebSurface() { + if (_webSurface) { + --_currentWebCount; + _webSurface->pause(); + _webSurface->disconnect(_connection); + QObject::disconnect(_mousePressConnection); + _mousePressConnection = QMetaObject::Connection(); + QObject::disconnect(_mouseReleaseConnection); + _mouseReleaseConnection = QMetaObject::Connection(); + QObject::disconnect(_mouseMoveConnection); + _mouseMoveConnection = QMetaObject::Connection(); + QObject::disconnect(_hoverLeaveConnection); + _hoverLeaveConnection = QMetaObject::Connection(); + + // The lifetime of the QML surface MUST be managed by the main thread + // Additionally, we MUST use local variables copied by value, rather than + // member variables, since they would implicitly refer to a this that + // is no longer valid + auto webSurface = _webSurface; + AbstractViewStateInterface::instance()->postLambdaEvent([webSurface] { + webSurface->deleteLater(); + }); + _webSurface = nullptr; + } +} + + +void RenderableWebEntityItem::update(const quint64& now) { + auto interval = now - _lastRenderTime; + if (interval > MAX_NO_RENDER_INTERVAL) { + destroyWebSurface(); + } +} diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.h b/libraries/entities-renderer/src/RenderableWebEntityItem.h index da1ddbf1a1..49a55b6b27 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.h +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.h @@ -18,6 +18,7 @@ class OffscreenQmlSurface; class QWindow; class QObject; +class EntityTreeRenderer; class RenderableWebEntityItem : public WebEntityItem { public: @@ -31,15 +32,22 @@ public: void setProxyWindow(QWindow* proxyWindow); QObject* getEventHandler(); + void update(const quint64& now) override; + bool needsToCallUpdate() const { return _webSurface != nullptr; } + SIMPLE_RENDERABLE(); private: + bool buildWebSurface(EntityTreeRenderer* renderer); + void destroyWebSurface(); + OffscreenQmlSurface* _webSurface{ nullptr }; QMetaObject::Connection _connection; uint32_t _texture{ 0 }; ivec2 _lastPress{ INT_MIN }; bool _pressed{ false }; ivec2 _lastMove{ INT_MIN }; + uint64_t _lastRenderTime{ 0 }; QMetaObject::Connection _mousePressConnection; QMetaObject::Connection _mouseReleaseConnection; From 942f2c13ab38c3a27be390291f546c0882c28b73 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Fri, 19 Feb 2016 15:58:13 -0800 Subject: [PATCH 59/72] Vive: smoother updates for IK driven by vive controllers Before this PR the simulation rate was clamped to never exceed 60htz. This had problems when waving the vive hand controllers in the world, they would jitter. The simulation rate is now clamped to never exceed 120 htz. This has the effect of synchronizing the display and the update rates to 90htz. Also there are improvements to vive support if threaded present is disabled. --- interface/src/Application.cpp | 3 ++- plugins/openvr/src/OpenVrDisplayPlugin.cpp | 9 +++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c202331041..670df573a7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -210,7 +210,7 @@ static const QString INFO_EDIT_ENTITIES_PATH = "html/edit-commands.html"; static const unsigned int THROTTLED_SIM_FRAMERATE = 15; static const int THROTTLED_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / THROTTLED_SIM_FRAMERATE; -static const unsigned int CAPPED_SIM_FRAMERATE = 60; +static const unsigned int CAPPED_SIM_FRAMERATE = 120; static const int CAPPED_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / CAPPED_SIM_FRAMERATE; static const uint32_t INVALID_FRAME = UINT32_MAX; @@ -1733,6 +1733,7 @@ bool Application::event(QEvent* event) { if ((int)event->type() == (int)Paint) { paintGL(); + return true; } if (!_keyboardFocusedItem.isInvalidID()) { diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index 353b248302..efd230bc28 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -101,9 +101,16 @@ glm::mat4 OpenVrDisplayPlugin::getHeadPose(uint32_t frameIndex) const { float frameDuration = 1.f / displayFrequency; float vsyncToPhotons = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_SecondsFromVsyncToPhotons_Float); +#if THREADED_PRESENT // TODO: this seems awfuly long, 44ms total, but it produced the best results. const float NUM_PREDICTION_FRAMES = 3.0f; float predictedSecondsFromNow = NUM_PREDICTION_FRAMES * frameDuration + vsyncToPhotons; +#else + uint64_t frameCounter; + float timeSinceLastVsync; + _system->GetTimeSinceLastVsync(&timeSinceLastVsync, &frameCounter); + float predictedSecondsFromNow = 3.0f * frameDuration - timeSinceLastVsync + vsyncToPhotons; +#endif vr::TrackedDevicePose_t predictedTrackedDevicePose[vr::k_unMaxTrackedDeviceCount]; _system->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseSeated, predictedSecondsFromNow, predictedTrackedDevicePose, vr::k_unMaxTrackedDeviceCount); @@ -126,8 +133,6 @@ void OpenVrDisplayPlugin::internalPresent() { _compositor->Submit(vr::Eye_Left, &texture, &leftBounds); _compositor->Submit(vr::Eye_Right, &texture, &rightBounds); - glFinish(); - vr::TrackedDevicePose_t currentTrackedDevicePose[vr::k_unMaxTrackedDeviceCount]; _compositor->WaitGetPoses(currentTrackedDevicePose, vr::k_unMaxTrackedDeviceCount, nullptr, 0); From 1fa6e294e7bc7e262e450c34cc93502b72ef1029 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 19 Feb 2016 17:49:33 -0800 Subject: [PATCH 60/72] allow mouse to move outside of the overlay extents --- interface/src/ui/ApplicationCompositor.cpp | 25 ++++++++++++++++------ interface/src/ui/ApplicationCompositor.h | 6 +++--- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 6c073be175..7f456acc2b 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -38,11 +38,12 @@ static const float reticleSize = TWO_PI / 100.0f; static const float CURSOR_PIXEL_SIZE = 32.0f; -static const float DEFAULT_HMD_UI_ANGULAR_SIZE_IN_RADIANS = (DEFAULT_HMD_UI_ANGULAR_SIZE / 180.0f) * PI; +static const float DEFAULT_HMD_UI_VERT_ANGULAR_SIZE_IN_RADIANS = (DEFAULT_HMD_UI_VERT_ANGULAR_SIZE / 180.0f) * PI; static const float DEFAULT_HMD_UI_HORZ_ANGULAR_SIZE_IN_RADIANS = (DEFAULT_HMD_UI_HORZ_ANGULAR_SIZE / 180.0f) * PI; -static const float MOUSE_PITCH_RANGE = DEFAULT_HMD_UI_ANGULAR_SIZE_IN_RADIANS; -static const float MOUSE_YAW_RANGE = VIRTUAL_SCREEN_SIZE_X / VIRTUAL_SCREEN_SIZE_Y * DEFAULT_HMD_UI_ANGULAR_SIZE_IN_RADIANS; -static const glm::vec2 MOUSE_RANGE(MOUSE_YAW_RANGE, MOUSE_PITCH_RANGE); + +//static const float MOUSE_PITCH_RANGE = DEFAULT_HMD_UI_ANGULAR_SIZE_IN_RADIANS; +//static const float MOUSE_YAW_RANGE = VIRTUAL_SCREEN_SIZE_X / VIRTUAL_SCREEN_SIZE_Y * DEFAULT_HMD_UI_ANGULAR_SIZE_IN_RADIANS; +//static const glm::vec2 MOUSE_RANGE(MOUSE_YAW_RANGE, MOUSE_PITCH_RANGE); static gpu::BufferPointer _hemiVertices; static gpu::BufferPointer _hemiIndices; @@ -378,10 +379,22 @@ glm::vec2 ApplicationCompositor::getReticlePosition() { } return toGlm(QCursor::pos()); } + void ApplicationCompositor::setReticlePosition(glm::vec2 position, bool sendFakeEvent) { if (qApp->isHMDMode()) { - glm::vec2 maxReticlePosition = qApp->getUiSize(); - _reticlePositionInHMD = glm::clamp(position, vec2(0), maxReticlePosition); + const float MOUSE_EXTENTS_VERT_ANGULAR_SIZE = 170.0f; // 5deg from poles + const float MOUSE_EXTENTS_VERT_PIXELS = VIRTUAL_SCREEN_SIZE_Y * (MOUSE_EXTENTS_VERT_ANGULAR_SIZE / DEFAULT_HMD_UI_VERT_ANGULAR_SIZE); + const float MOUSE_EXTENTS_HORZ_ANGULAR_SIZE = 360.0f; // full sphere + const float MOUSE_EXTENTS_HORZ_PIXELS = VIRTUAL_SCREEN_SIZE_X * (MOUSE_EXTENTS_HORZ_ANGULAR_SIZE / DEFAULT_HMD_UI_HORZ_ANGULAR_SIZE); + + glm::vec2 maxOverlayPosition = qApp->getUiSize(); + float extaPixelsX = (MOUSE_EXTENTS_HORZ_PIXELS - maxOverlayPosition.x) / 2.0f; + float extaPixelsY = (MOUSE_EXTENTS_VERT_PIXELS - maxOverlayPosition.y) / 2.0f; + glm::vec2 mouseExtra { extaPixelsX, extaPixelsY }; + glm::vec2 minMouse = vec2(0) - mouseExtra; + glm::vec2 maxMouse = maxOverlayPosition + mouseExtra; + + _reticlePositionInHMD = glm::clamp(position, minMouse, maxMouse); if (sendFakeEvent) { // in HMD mode we need to fake our mouse moves... diff --git a/interface/src/ui/ApplicationCompositor.h b/interface/src/ui/ApplicationCompositor.h index 7523204f50..db8f42881e 100644 --- a/interface/src/ui/ApplicationCompositor.h +++ b/interface/src/ui/ApplicationCompositor.h @@ -35,7 +35,7 @@ const float MAGNIFY_MULT = 2.0f; const int VIRTUAL_SCREEN_SIZE_X = 3840; const int VIRTUAL_SCREEN_SIZE_Y = 1536; const float DEFAULT_HMD_UI_HORZ_ANGULAR_SIZE = 180.0f; -const float DEFAULT_HMD_UI_ANGULAR_SIZE = DEFAULT_HMD_UI_HORZ_ANGULAR_SIZE * (float)VIRTUAL_SCREEN_SIZE_Y / (float)VIRTUAL_SCREEN_SIZE_X; +const float DEFAULT_HMD_UI_VERT_ANGULAR_SIZE = DEFAULT_HMD_UI_HORZ_ANGULAR_SIZE * (float)VIRTUAL_SCREEN_SIZE_Y / (float)VIRTUAL_SCREEN_SIZE_X; // Handles the drawing of the overlays to the screen // TODO, move divide up the rendering, displaying and input handling @@ -115,8 +115,8 @@ private: QString _hoverItemDescription; quint64 _hoverItemEnterUsecs { 0 }; - float _hmdUIAngularSize { DEFAULT_HMD_UI_ANGULAR_SIZE }; - float _textureFov { glm::radians(DEFAULT_HMD_UI_ANGULAR_SIZE) }; + float _hmdUIAngularSize { DEFAULT_HMD_UI_VERT_ANGULAR_SIZE }; + float _textureFov { glm::radians(DEFAULT_HMD_UI_VERT_ANGULAR_SIZE) }; float _textureAspectRatio { 1.0f }; int _hemiVerticesID { GeometryCache::UNKNOWN_ID }; From 2810be8787ff2bcf0bca3a6fe2ff9e8054748be3 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 19 Feb 2016 17:57:49 -0800 Subject: [PATCH 61/72] fix scripts to use new API --- examples/grab.js | 7 ++----- examples/gracefulControls.js | 14 +++++++------- examples/libraries/entityCameraTool.js | 8 ++++---- examples/mouseLook.js | 10 +++++----- 4 files changed, 18 insertions(+), 21 deletions(-) diff --git a/examples/grab.js b/examples/grab.js index 8c799ca62f..c79259ed57 100644 --- a/examples/grab.js +++ b/examples/grab.js @@ -158,10 +158,7 @@ Mouse.prototype.startRotateDrag = function() { x: this.current.x, y: this.current.y }; - this.cursorRestore = { - x: Window.getCursorPositionX(), - y: Window.getCursorPositionY() - }; + this.cursorRestore = Reticle.getPosition(); } Mouse.prototype.getDrag = function() { @@ -177,7 +174,7 @@ Mouse.prototype.getDrag = function() { } Mouse.prototype.restoreRotateCursor = function() { - Window.setCursorPosition(this.cursorRestore.x, this.cursorRestore.y); + Reticle.setPosition(this.cursorRestore); this.current = { x: this.rotateStart.x, y: this.rotateStart.y diff --git a/examples/gracefulControls.js b/examples/gracefulControls.js index e2b603c5d7..ab5de48ae2 100644 --- a/examples/gracefulControls.js +++ b/examples/gracefulControls.js @@ -54,8 +54,8 @@ var velocity = { x: 0, y: 0, z: 0 }; var velocityVertical = 0; var enabled = false; -var lastX = Window.getCursorPositionX(); -var lastY = Window.getCursorPositionY(); +var lastX = Reticle.getPosition().x; +var lastY = Reticle.getPosition().y; var yawFromMouse = 0; var pitchFromMouse = 0; @@ -109,8 +109,8 @@ function update(dt) { } if (enabled && Window.hasFocus()) { - var x = Window.getCursorPositionX(); - var y = Window.getCursorPositionY(); + var x = Reticle.getPosition().x; + var y = Reticle.getPosition().y; yawFromMouse += ((x - lastX) * movementParameters.MOUSE_YAW_SCALE * movementParameters.MOUSE_SENSITIVITY); pitchFromMouse += ((y - lastY) * movementParameters.MOUSE_PITCH_SCALE * movementParameters.MOUSE_SENSITIVITY); @@ -173,7 +173,7 @@ function scriptEnding() { function resetCursorPosition() { var newX = Window.x + Window.innerWidth / 2; var newY = Window.y + Window.innerHeight / 2; - Window.setCursorPosition(newX, newY); + Reticle.setPosition({ x: newX, y: newY}); lastX = newX; lastY = newY; } @@ -194,7 +194,7 @@ function enable() { for (var i = 0; i < CAPTURED_KEYS.length; i++) { Controller.captureKeyEvents({ text: CAPTURED_KEYS[i] }); } - Window.setCursorVisible(false); + Reticle.setVisible(false); Script.update.connect(update); } } @@ -205,7 +205,7 @@ function disable() { for (var i = 0; i < CAPTURED_KEYS.length; i++) { Controller.releaseKeyEvents({ text: CAPTURED_KEYS[i] }); } - Window.setCursorVisible(true); + Reticle.setVisible(true); Script.update.disconnect(update); } } diff --git a/examples/libraries/entityCameraTool.js b/examples/libraries/entityCameraTool.js index d209ed6c5c..a8e9335956 100644 --- a/examples/libraries/entityCameraTool.js +++ b/examples/libraries/entityCameraTool.js @@ -281,8 +281,8 @@ CameraManager = function() { that.mouseMoveEvent = function(event) { if (that.enabled && that.mode != MODE_INACTIVE) { - var x = Window.getCursorPositionX(); - var y = Window.getCursorPositionY(); + var x = Reticle.getPosition().x; + var y = Reticle.getPosition().y; if (!hasDragged) { that.lastMousePosition.x = x; that.lastMousePosition.y = y; @@ -337,7 +337,7 @@ CameraManager = function() { } if (updatePosition) { - Window.setCursorPosition(newX, newY); + Reticle.setPosition({ x: newX, y: newY}); } that.lastMousePosition.x = newX; @@ -384,7 +384,7 @@ CameraManager = function() { if (!that.enabled) return; that.mode = MODE_INACTIVE; - Window.setCursorVisible(true); + Reticle.setVisible(true); } diff --git a/examples/mouseLook.js b/examples/mouseLook.js index 81bc9d2813..ea97ead8e9 100644 --- a/examples/mouseLook.js +++ b/examples/mouseLook.js @@ -9,8 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -var lastX = Window.getCursorPositionX(); -var lastY = Window.getCursorPositionY(); +var lastX = Reticle.getPosition().x; +var lastY = Reticle.getPosition().y; var yawFromMouse = 0; var pitchFromMouse = 0; @@ -121,9 +121,9 @@ var mouseLook = (function () { function onScriptUpdate(dt) { if (active && Window.hasFocus()) { - var x = Window.getCursorPositionX(); + var x = Reticle.getPosition().x; // I'm not sure why this + 0.5 is necessary? - var y = Window.getCursorPositionY() + 0.5; + var y = Reticle.getPosition().y; + 0.5; yawFromMouse += ((x - lastX) * movementParameters.MOUSE_YAW_SCALE * movementParameters.MOUSE_SENSITIVITY); pitchFromMouse += ((y - lastY) * movementParameters.MOUSE_PITCH_SCALE * movementParameters.MOUSE_SENSITIVITY); @@ -155,7 +155,7 @@ var mouseLook = (function () { function resetCursorPosition() { var newX = Window.x + Window.innerWidth / 2.0; var newY = Window.y + Window.innerHeight / 2.0; - Window.setCursorPosition(newX, newY); + Reticle.setPosition({ x: newX, y: newY}); lastX = newX; lastY = newY; } From 04fa37324f0bcc89a159e3088a3a259fd11563c0 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 19 Feb 2016 18:24:32 -0800 Subject: [PATCH 62/72] tweak to virtual desktop size, to make text more readable, 240d horz FOV --- interface/src/ui/ApplicationCompositor.h | 6 +++--- .../src/display-plugins/hmd/HmdDisplayPlugin.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/interface/src/ui/ApplicationCompositor.h b/interface/src/ui/ApplicationCompositor.h index db8f42881e..d8761bb9b5 100644 --- a/interface/src/ui/ApplicationCompositor.h +++ b/interface/src/ui/ApplicationCompositor.h @@ -32,9 +32,9 @@ const float MAGNIFY_WIDTH = 220.0f; const float MAGNIFY_HEIGHT = 100.0f; const float MAGNIFY_MULT = 2.0f; -const int VIRTUAL_SCREEN_SIZE_X = 3840; -const int VIRTUAL_SCREEN_SIZE_Y = 1536; -const float DEFAULT_HMD_UI_HORZ_ANGULAR_SIZE = 180.0f; +const int VIRTUAL_SCREEN_SIZE_X = 3960; // ~10% more pixel density than old version, 72dx240d FOV +const int VIRTUAL_SCREEN_SIZE_Y = 1188; // ~10% more pixel density than old version, 72dx240d FOV +const float DEFAULT_HMD_UI_HORZ_ANGULAR_SIZE = 240.0f; const float DEFAULT_HMD_UI_VERT_ANGULAR_SIZE = DEFAULT_HMD_UI_HORZ_ANGULAR_SIZE * (float)VIRTUAL_SCREEN_SIZE_Y / (float)VIRTUAL_SCREEN_SIZE_X; // Handles the drawing of the overlays to the screen diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h index 9ec40e02a8..227f377e1b 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h @@ -20,8 +20,8 @@ public: glm::mat4 getCullingProjection(const glm::mat4& baseProjection) const override final { return _cullingProjection; } glm::uvec2 getRecommendedUiSize() const override final { // FIXME - would be good to have these values sync with ApplicationCompositor in a better way. - const int VIRTUAL_SCREEN_SIZE_X = 3840; - const int VIRTUAL_SCREEN_SIZE_Y = 1536; + const int VIRTUAL_SCREEN_SIZE_X = 3960; // ~10% more pixel density than old version, 72dx240d FOV + const int VIRTUAL_SCREEN_SIZE_Y = 1188; // ~10% more pixel density than old version, 72dx240d FOV auto result = uvec2(VIRTUAL_SCREEN_SIZE_X, VIRTUAL_SCREEN_SIZE_Y); return result; } From 4e2c514eb1d88763728fc636dd549974757c0c8c Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 19 Feb 2016 18:27:25 -0800 Subject: [PATCH 63/72] fix mac warning --- interface/src/ui/ApplicationCompositor.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 7f456acc2b..e8c5374baa 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -38,13 +38,6 @@ static const float reticleSize = TWO_PI / 100.0f; static const float CURSOR_PIXEL_SIZE = 32.0f; -static const float DEFAULT_HMD_UI_VERT_ANGULAR_SIZE_IN_RADIANS = (DEFAULT_HMD_UI_VERT_ANGULAR_SIZE / 180.0f) * PI; -static const float DEFAULT_HMD_UI_HORZ_ANGULAR_SIZE_IN_RADIANS = (DEFAULT_HMD_UI_HORZ_ANGULAR_SIZE / 180.0f) * PI; - -//static const float MOUSE_PITCH_RANGE = DEFAULT_HMD_UI_ANGULAR_SIZE_IN_RADIANS; -//static const float MOUSE_YAW_RANGE = VIRTUAL_SCREEN_SIZE_X / VIRTUAL_SCREEN_SIZE_Y * DEFAULT_HMD_UI_ANGULAR_SIZE_IN_RADIANS; -//static const glm::vec2 MOUSE_RANGE(MOUSE_YAW_RANGE, MOUSE_PITCH_RANGE); - static gpu::BufferPointer _hemiVertices; static gpu::BufferPointer _hemiIndices; static int _hemiIndexCount{ 0 }; From 9c3abd3eb75d983438b043dbde8adf61d7a1c82a Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Sat, 20 Feb 2016 11:40:30 -0800 Subject: [PATCH 64/72] some cleanup and standardization in how headPose is gathered --- .../src/scripting/HMDScriptingInterface.cpp | 4 ++ .../src/scripting/HMDScriptingInterface.h | 1 + interface/src/ui/ApplicationCompositor.cpp | 57 +++++++------------ interface/src/ui/ApplicationCompositor.h | 1 + 4 files changed, 27 insertions(+), 36 deletions(-) diff --git a/interface/src/scripting/HMDScriptingInterface.cpp b/interface/src/scripting/HMDScriptingInterface.cpp index 3f9b8ee598..d7013ad407 100644 --- a/interface/src/scripting/HMDScriptingInterface.cpp +++ b/interface/src/scripting/HMDScriptingInterface.cpp @@ -30,6 +30,10 @@ glm::vec2 HMDScriptingInterface::overlayFromWorldPoint(const glm::vec3& position return qApp->getApplicationCompositor().overlayFromSphereSurface(position); } +glm::vec3 HMDScriptingInterface::worldPointFromOverlay(const glm::vec2& overlay) const { + return qApp->getApplicationCompositor().sphereSurfaceFromOverlay(overlay); +} + glm::vec2 HMDScriptingInterface::sphericalToOverlay(const glm::vec2 & position) const { return qApp->getApplicationCompositor().sphericalToOverlay(position); } diff --git a/interface/src/scripting/HMDScriptingInterface.h b/interface/src/scripting/HMDScriptingInterface.h index 2ead84cab1..b36048788a 100644 --- a/interface/src/scripting/HMDScriptingInterface.h +++ b/interface/src/scripting/HMDScriptingInterface.h @@ -29,6 +29,7 @@ class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Depen public: Q_INVOKABLE glm::vec3 calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction) const; Q_INVOKABLE glm::vec2 overlayFromWorldPoint(const glm::vec3& position) const; + Q_INVOKABLE glm::vec3 worldPointFromOverlay(const glm::vec2& overlay) const; Q_INVOKABLE glm::vec2 sphericalToOverlay(const glm::vec2 & sphericalPos) const; Q_INVOKABLE glm::vec2 overlayToSpherical(const glm::vec2 & overlayPos) const; diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index e8c5374baa..44f37f55c7 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -257,9 +257,9 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int mat4 camMat; _cameraBaseTransform.getMatrix(camMat); auto displayPlugin = qApp->getActiveDisplayPlugin(); - auto headPose = displayPlugin->getHeadPose(qApp->getFrameCount()); + auto headPose = qApp->getHMDSensorPose(); auto eyeToHead = displayPlugin->getEyeToHeadTransform((Eye)eye); - camMat = (headPose * eyeToHead) * camMat; + camMat = (headPose * eyeToHead) * camMat; // FIXME - why are not all transforms are doing this aditioanl eyeToHead batch.setViewportTransform(renderArgs->_viewport); batch.setViewTransform(camMat); batch.setProjectionTransform(qApp->getEyeProjection(eye)); @@ -425,41 +425,16 @@ glm::vec2 ApplicationCompositor::getReticleMaximumPosition() const { return result; } -// FIXME - this probably is hella buggy and probably doesn't work correctly -// we should kill it asap. void ApplicationCompositor::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction) const { - const glm::vec2 projection = overlayToSpherical(cursorPos); - // The overlay space orientation of the mouse coordinates - const glm::quat cursorOrientation(glm::vec3(-projection.y, projection.x, 0.0f)); - - // The orientation and position of the HEAD, not the overlay - glm::vec3 worldSpaceHeadPosition = qApp->getCamera()->getPosition(); - glm::quat worldSpaceOrientation = qApp->getCamera()->getOrientation(); - - auto headPose = qApp->getHMDSensorPose(); - auto headOrientation = glm::quat_cast(headPose); - auto headTranslation = extractTranslation(headPose); - - auto overlayOrientation = worldSpaceOrientation * glm::inverse(headOrientation); - auto overlayPosition = worldSpaceHeadPosition - (overlayOrientation * headTranslation); - if (Menu::getInstance()->isOptionChecked(MenuOption::StandingHMDSensorMode)) { - overlayPosition = _modelTransform.getTranslation(); - overlayOrientation = _modelTransform.getRotation(); - } - - // Intersection in world space - glm::vec3 worldSpaceIntersection = ((overlayOrientation * (cursorOrientation * Vectors::FRONT)) * _oculusUIRadius) + overlayPosition; - - origin = worldSpaceHeadPosition; - direction = glm::normalize(worldSpaceIntersection - worldSpaceHeadPosition); + auto surfacePointAt = sphereSurfaceFromOverlay(cursorPos); // in world space + glm::vec3 worldSpaceCameraPosition = qApp->getCamera()->getPosition(); + origin = worldSpaceCameraPosition; + direction = glm::normalize(surfacePointAt - worldSpaceCameraPosition); } //Finds the collision point of a world space ray bool ApplicationCompositor::calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction, glm::vec3& result) const { - - auto displayPlugin = qApp->getActiveDisplayPlugin(); - auto headPose = displayPlugin->getHeadPose(qApp->getFrameCount()); - + auto headPose = qApp->getHMDSensorPose(); auto myCamera = qApp->getCamera(); mat4 cameraMat = myCamera->getTransform(); auto UITransform = cameraMat * glm::inverse(headPose); @@ -604,9 +579,7 @@ glm::vec2 ApplicationCompositor::overlayToSpherical(const glm::vec2& overlayPos } glm::vec2 ApplicationCompositor::overlayFromSphereSurface(const glm::vec3& sphereSurfacePoint) const { - - auto displayPlugin = qApp->getActiveDisplayPlugin(); - auto headPose = displayPlugin->getHeadPose(qApp->getFrameCount()); + auto headPose = qApp->getHMDSensorPose(); auto myCamera = qApp->getCamera(); mat4 cameraMat = myCamera->getTransform(); auto UITransform = cameraMat * glm::inverse(headPose); @@ -614,12 +587,24 @@ glm::vec2 ApplicationCompositor::overlayFromSphereSurface(const glm::vec3& spher auto relativePosition = vec3(relativePosition4) / relativePosition4.w; auto center = vec3(0); // center of HUD in HUD space auto direction = relativePosition - center; // direction to relative position in HUD space - glm::vec2 polar = glm::vec2(glm::atan(direction.x, -direction.z), glm::asin(direction.y)) * -1.0f; auto overlayPos = sphericalToOverlay(polar); return overlayPos; } +glm::vec3 ApplicationCompositor::sphereSurfaceFromOverlay(const glm::vec2& overlay) const { + auto spherical = overlayToSpherical(overlay); + auto sphereSurfacePoint = getPoint(spherical.x, spherical.y); + auto headPose = qApp->getHMDSensorPose(); + auto myCamera = qApp->getCamera(); + mat4 cameraMat = myCamera->getTransform(); + auto UITransform = cameraMat * glm::inverse(headPose); + auto position4 = UITransform * vec4(sphereSurfacePoint, 1); + auto position = vec3(position4) / position4.w; + return position; +} + + void ApplicationCompositor::updateTooltips() { if (_hoverItemId != _noItemId) { quint64 hoverDuration = usecTimestampNow() - _hoverItemEnterUsecs; diff --git a/interface/src/ui/ApplicationCompositor.h b/interface/src/ui/ApplicationCompositor.h index d8761bb9b5..0566f63944 100644 --- a/interface/src/ui/ApplicationCompositor.h +++ b/interface/src/ui/ApplicationCompositor.h @@ -66,6 +66,7 @@ public: uint32_t getOverlayTexture() const; glm::vec2 overlayFromSphereSurface(const glm::vec3& sphereSurfacePoint) const; + glm::vec3 sphereSurfaceFromOverlay(const glm::vec2& overlay) const; void setCameraBaseTransform(const Transform& transform) { _cameraBaseTransform = transform; } const Transform& getCameraBaseTransform() const { return _cameraBaseTransform; } From 786747c2d7311851ae80387a0684a8d0a0a8576c Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sat, 20 Feb 2016 12:01:34 -0800 Subject: [PATCH 65/72] Properly preserve and restore the GL context after building a web entity --- .../entities-renderer/src/RenderableWebEntityItem.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index ade44f94a0..b0aeaffd4e 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -58,7 +58,9 @@ bool RenderableWebEntityItem::buildWebSurface(EntityTreeRenderer* renderer) { qDebug() << "Building web surface"; ++_currentWebCount; + // Save the original GL context, because creating a QML surface will create a new context QOpenGLContext * currentContext = QOpenGLContext::currentContext(); + QSurface * currentSurface = currentContext->surface(); _webSurface = new OffscreenQmlSurface(); _webSurface->create(currentContext); _webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/")); @@ -68,6 +70,8 @@ bool RenderableWebEntityItem::buildWebSurface(EntityTreeRenderer* renderer) { _connection = QObject::connect(_webSurface, &OffscreenQmlSurface::textureUpdated, [&](GLuint textureId) { _texture = textureId; }); + // Restore the original GL context + currentContext->makeCurrent(currentSurface); auto forwardMouseEvent = [=](const RayToEntityIntersectionResult& intersection, const QMouseEvent* event, unsigned int deviceId) { // Ignore mouse interaction if we're locked @@ -142,7 +146,6 @@ bool RenderableWebEntityItem::buildWebSurface(EntityTreeRenderer* renderer) { QCoreApplication::sendEvent(_webSurface->getWindow(), &mappedEvent); } }; - _mousePressConnection = QObject::connect(renderer, &EntityTreeRenderer::mousePressOnEntity, forwardMouseEvent); _mouseReleaseConnection = QObject::connect(renderer, &EntityTreeRenderer::mouseReleaseOnEntity, forwardMouseEvent); _mouseMoveConnection = QObject::connect(renderer, &EntityTreeRenderer::mouseMoveOnEntity, forwardMouseEvent); @@ -176,16 +179,12 @@ void RenderableWebEntityItem::render(RenderArgs* args) { } _lastRenderTime = usecTimestampNow(); - QOpenGLContext * currentContext = QOpenGLContext::currentContext(); - QSurface * currentSurface = currentContext->surface(); - glm::vec2 dims = glm::vec2(getDimensions()); dims *= METERS_TO_INCHES * DPI; // The offscreen surface is idempotent for resizes (bails early // if it's a no-op), so it's safe to just call resize every frame // without worrying about excessive overhead. _webSurface->resize(QSize(dims.x, dims.y)); - currentContext->makeCurrent(currentSurface); PerformanceTimer perfTimer("RenderableWebEntityItem::render"); Q_ASSERT(getType() == EntityTypes::Web); From 58539171a31287bbbc6a200fc7b28fa9399dfc91 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Sat, 20 Feb 2016 22:46:19 +0100 Subject: [PATCH 66/72] give particle trails a nice smooth path between frames --- libraries/entities/src/ParticleEffectEntityItem.cpp | 9 ++++++--- libraries/entities/src/ParticleEffectEntityItem.h | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 16196aa129..4b798cbcd9 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -103,6 +103,7 @@ EntityItemPointer ParticleEffectEntityItem::factory(const EntityItemID& entityID // our non-pure virtual subclass for now... ParticleEffectEntityItem::ParticleEffectEntityItem(const EntityItemID& entityItemID) : EntityItem(entityItemID), + _previousPosition(getPosition()), _lastSimulated(usecTimestampNow()) { _type = EntityTypes::ParticleEffect; @@ -623,7 +624,8 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { } // emit a new particle at tail index. - _particles.push_back(createParticle()); + _particles.push_back(createParticle(glm::mix(_previousPosition, getPosition(), + (deltaTime - timeLeftInFrame) / deltaTime))); auto particle = _particles.back(); particle.lifetime += timeLeftInFrame; @@ -637,15 +639,16 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { _timeUntilNextEmit -= timeLeftInFrame; } + _previousPosition = getPosition(); } -ParticleEffectEntityItem::Particle ParticleEffectEntityItem::createParticle() { +ParticleEffectEntityItem::Particle ParticleEffectEntityItem::createParticle(const glm::vec3& position) { Particle particle; particle.seed = randFloatInRange(-1.0f, 1.0f); if (getEmitterShouldTrail()) { - particle.position = getPosition(); + particle.position = position; } // Position, velocity, and acceleration if (_polarStart == 0.0f && _polarFinish == 0.0f && _emitDimensions.z == 0.0f) { diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 5afcbe2ae1..ba6f32b51f 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -227,7 +227,7 @@ protected: bool isAnimatingSomething() const; - Particle createParticle(); + Particle createParticle(const glm::vec3& position); void stepSimulation(float deltaTime); void integrateParticle(Particle& particle, float deltaTime); @@ -275,7 +275,7 @@ protected: float _azimuthStart = DEFAULT_AZIMUTH_START; float _azimuthFinish = DEFAULT_AZIMUTH_FINISH; - + glm::vec3 _previousPosition; quint64 _lastSimulated { 0 }; bool _isEmitting { true }; From 32a7179c62e1cad23c599919e9328281f470413e Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Sun, 21 Feb 2016 09:59:19 -0800 Subject: [PATCH 67/72] CR feedback --- interface/src/Application.cpp | 2 +- interface/src/Application.h | 2 +- interface/src/ui/ApplicationCompositor.cpp | 14 +++++++----- interface/src/ui/ApplicationCompositor.h | 26 +++++++++++----------- interface/src/ui/ApplicationOverlay.cpp | 10 +++------ 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5bd93b1067..8357fff400 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4720,7 +4720,7 @@ glm::uvec2 Application::getCanvasSize() const { return glm::uvec2(_glWidget->width(), _glWidget->height()); } -QRect Application::getApplicationGeometry() const { +QRect Application::getRenderingGeometry() const { auto geometry = _glWidget->geometry(); auto topLeft = geometry.topLeft(); auto topLeftScreen = _glWidget->mapToGlobal(topLeft); diff --git a/interface/src/Application.h b/interface/src/Application.h index 6f115c6f64..67b776b260 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -114,7 +114,7 @@ public: bool eventFilter(QObject* object, QEvent* event) override; glm::uvec2 getCanvasSize() const; - QRect getApplicationGeometry() const; + QRect getRenderingGeometry() const; glm::uvec2 getUiSize() const; QSize getDeviceSize() const; diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 44f37f55c7..636a4ac420 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -113,6 +113,7 @@ ApplicationCompositor::ApplicationCompositor() : _reticleInterface(new ReticleInterface(this)) { + _reticlePositionInHMD.store(glm::vec2(0.0f)); auto geometryCache = DependencyManager::get(); _reticleQuad = geometryCache->allocateID(); @@ -300,7 +301,8 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int QPointF ApplicationCompositor::getMouseEventPosition(QMouseEvent* event) { if (qApp->isHMDMode()) { - return QPointF(_reticlePositionInHMD.x, _reticlePositionInHMD.y); + auto reticlePositionInHMD = _reticlePositionInHMD.load(); + return QPointF(reticlePositionInHMD.x, reticlePositionInHMD.y); } return event->localPos(); } @@ -314,7 +316,7 @@ void ApplicationCompositor::handleLeaveEvent() { if (shouldCaptureMouse()) { QWidget* mainWidget = (QWidget*)qApp->getWindow(); - QRect mainWidgetFrame = qApp->getApplicationGeometry(); + QRect mainWidgetFrame = qApp->getRenderingGeometry(); QRect uncoveredRect = mainWidgetFrame; foreach(QWidget* widget, QApplication::topLevelWidgets()) { if (widget->isWindow() && widget->isVisible() && widget != mainWidget) { @@ -355,7 +357,8 @@ bool ApplicationCompositor::handleRealMouseMoveEvent(bool sendFakeEvent) { if (shouldCaptureMouse()) { auto newPosition = QCursor::pos(); auto changeInRealMouse = newPosition - _lastKnownRealMouse; - auto newReticlePosition = _reticlePositionInHMD + toGlm(changeInRealMouse); + auto reticlePositionInHMD = _reticlePositionInHMD.load(); + auto newReticlePosition = reticlePositionInHMD + toGlm(changeInRealMouse); setReticlePosition(newReticlePosition, sendFakeEvent); _ignoreMouseMove = true; QCursor::setPos(QPoint(_lastKnownRealMouse.x(), _lastKnownRealMouse.y())); // move cursor back to where it was @@ -387,11 +390,12 @@ void ApplicationCompositor::setReticlePosition(glm::vec2 position, bool sendFake glm::vec2 minMouse = vec2(0) - mouseExtra; glm::vec2 maxMouse = maxOverlayPosition + mouseExtra; - _reticlePositionInHMD = glm::clamp(position, minMouse, maxMouse); + auto reticlePositionInHMD = glm::clamp(position, minMouse, maxMouse); + _reticlePositionInHMD.store(reticlePositionInHMD); if (sendFakeEvent) { // in HMD mode we need to fake our mouse moves... - QPoint globalPos(_reticlePositionInHMD.x, _reticlePositionInHMD.y); + QPoint globalPos(reticlePositionInHMD.x, reticlePositionInHMD.y); auto button = Qt::NoButton; auto buttons = QApplication::mouseButtons(); auto modifiers = QApplication::keyboardModifiers(); diff --git a/interface/src/ui/ApplicationCompositor.h b/interface/src/ui/ApplicationCompositor.h index 0566f63944..672915d58d 100644 --- a/interface/src/ui/ApplicationCompositor.h +++ b/interface/src/ui/ApplicationCompositor.h @@ -9,11 +9,13 @@ #ifndef hifi_ApplicationCompositor_h #define hifi_ApplicationCompositor_h +#include +#include + #include #include #include #include -#include #include #include @@ -81,16 +83,16 @@ public: float getAlpha() const { return _alpha; } void setAlpha(float alpha) { _alpha = alpha; } - Q_INVOKABLE bool getReticleVisible() { return _reticleVisible; } - Q_INVOKABLE void setReticleVisible(bool visible) { _reticleVisible = visible; } + bool getReticleVisible() { return _reticleVisible; } + void setReticleVisible(bool visible) { _reticleVisible = visible; } - Q_INVOKABLE float getReticleDepth() { return _reticleDepth; } - Q_INVOKABLE void setReticleDepth(float depth) { _reticleDepth = depth; } + float getReticleDepth() { return _reticleDepth; } + void setReticleDepth(float depth) { _reticleDepth = depth; } - Q_INVOKABLE glm::vec2 getReticlePosition(); - Q_INVOKABLE void setReticlePosition(glm::vec2 position, bool sendFakeEvent = true); + glm::vec2 getReticlePosition(); + void setReticlePosition(glm::vec2 position, bool sendFakeEvent = true); - Q_INVOKABLE glm::vec2 getReticleMaximumPosition() const; + glm::vec2 getReticleMaximumPosition() const; ReticleInterface* getReticleInterface() { return _reticleInterface; } @@ -138,19 +140,17 @@ private: std::unique_ptr _alphaPropertyAnimation; - bool _reticleVisible { true }; - float _reticleDepth { 1.0f }; + std::atomic _reticleVisible { true }; + std::atomic _reticleDepth { 1.0f }; // NOTE: when the compositor is running in HMD mode, it will control the reticle position as a custom // application specific position, when it's in desktop mode, the reticle position will simply move // the system mouse. - glm::vec2 _reticlePositionInHMD{ 0.0f, 0.0f }; + std::atomic _reticlePositionInHMD; QPointF _lastKnownRealMouse; - QPoint _lastKnownCursorPos; bool _ignoreMouseMove { false }; ReticleInterface* _reticleInterface; - }; // Scripting interface available to control the Reticle diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index b654f797ec..67b5135e0c 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -252,12 +252,8 @@ void ApplicationOverlay::buildFramebufferObject() { PROFILE_RANGE(__FUNCTION__); auto uiSize = qApp->getUiSize(); - QSize desiredSize (uiSize.x, uiSize.y); - int currentWidth = _overlayFramebuffer ? _overlayFramebuffer->getWidth() : 0; - int currentHeight = _overlayFramebuffer ? _overlayFramebuffer->getHeight() : 0; - QSize frameBufferCurrentSize(currentWidth, currentHeight); - if (_overlayFramebuffer && desiredSize == frameBufferCurrentSize) { + if (_overlayFramebuffer && uiSize == _overlayFramebuffer->getSize()) { // Already built return; } @@ -271,8 +267,8 @@ void ApplicationOverlay::buildFramebufferObject() { _overlayFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); auto colorFormat = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); - auto width = desiredSize.width(); - auto height = desiredSize.height(); + auto width = uiSize.x; + auto height = uiSize.y; auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR); _overlayColorTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); From 3e6cddede303b223184f0fb4eae308209daf6afc Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Sun, 21 Feb 2016 10:03:51 -0800 Subject: [PATCH 68/72] CR feedback --- interface/src/Application.cpp | 2 +- interface/src/Application.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8357fff400..7c1fd9279b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3598,7 +3598,7 @@ glm::vec3 Application::getSunDirection() { // FIXME, preprocessor guard this check to occur only in DEBUG builds static QThread * activeRenderingThread = nullptr; -PickRay Application::computePickRay(float x, float y) { +PickRay Application::computePickRay(float x, float y) const { vec2 pickPoint { x, y }; PickRay result; if (isHMDMode()) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 67b776b260..96bafce23f 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -168,7 +168,7 @@ public: virtual ViewFrustum* getCurrentViewFrustum() override { return getDisplayViewFrustum(); } virtual QThread* getMainThread() override { return thread(); } - virtual PickRay computePickRay(float x, float y) override; + virtual PickRay computePickRay(float x, float y) const override; virtual glm::vec3 getAvatarPosition() const override; virtual qreal getDevicePixelRatio() override; From f41ebdf71d787d8916feaa63af80ada12d1d31ce Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Sun, 21 Feb 2016 10:03:54 -0800 Subject: [PATCH 69/72] CR feedback --- libraries/render-utils/src/AbstractViewStateInterface.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/AbstractViewStateInterface.h b/libraries/render-utils/src/AbstractViewStateInterface.h index 1165816dd2..815cb45423 100644 --- a/libraries/render-utils/src/AbstractViewStateInterface.h +++ b/libraries/render-utils/src/AbstractViewStateInterface.h @@ -36,7 +36,7 @@ public: virtual QThread* getMainThread() = 0; - virtual PickRay computePickRay(float x, float y) = 0; + virtual PickRay computePickRay(float x, float y) const = 0; virtual glm::vec3 getAvatarPosition() const = 0; From 2c7c6be6a6a3dee80ea22ead60a18d85d5267549 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Sun, 21 Feb 2016 10:40:11 -0800 Subject: [PATCH 70/72] fix build buster --- libraries/entities-renderer/src/RenderableWebEntityItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index b0aeaffd4e..ce3faeb196 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -73,7 +73,7 @@ bool RenderableWebEntityItem::buildWebSurface(EntityTreeRenderer* renderer) { // Restore the original GL context currentContext->makeCurrent(currentSurface); - auto forwardMouseEvent = [=](const RayToEntityIntersectionResult& intersection, const QMouseEvent* event, unsigned int deviceId) { + auto forwardMouseEvent = [=](const RayToEntityIntersectionResult& intersection, const QMouseEvent* event) { // Ignore mouse interaction if we're locked if (this->getLocked()) { return; From 68771c92f780229124f3b8262303f409ee3b3585 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Sun, 21 Feb 2016 11:38:26 -0800 Subject: [PATCH 71/72] change position to use mutex instead of atomic<> --- interface/src/ui/ApplicationCompositor.cpp | 18 ++++++++++-------- interface/src/ui/ApplicationCompositor.h | 4 +++- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 636a4ac420..8f8b97a2e1 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -113,7 +113,6 @@ ApplicationCompositor::ApplicationCompositor() : _reticleInterface(new ReticleInterface(this)) { - _reticlePositionInHMD.store(glm::vec2(0.0f)); auto geometryCache = DependencyManager::get(); _reticleQuad = geometryCache->allocateID(); @@ -301,8 +300,8 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int QPointF ApplicationCompositor::getMouseEventPosition(QMouseEvent* event) { if (qApp->isHMDMode()) { - auto reticlePositionInHMD = _reticlePositionInHMD.load(); - return QPointF(reticlePositionInHMD.x, reticlePositionInHMD.y); + QMutexLocker locker(&_reticlePositionInHMDLock); + return QPointF(_reticlePositionInHMD.x, _reticlePositionInHMD.y); } return event->localPos(); } @@ -355,10 +354,11 @@ bool ApplicationCompositor::handleRealMouseMoveEvent(bool sendFakeEvent) { // If we're in HMD mode if (shouldCaptureMouse()) { + QMutexLocker locker(&_reticlePositionInHMDLock); + auto newPosition = QCursor::pos(); auto changeInRealMouse = newPosition - _lastKnownRealMouse; - auto reticlePositionInHMD = _reticlePositionInHMD.load(); - auto newReticlePosition = reticlePositionInHMD + toGlm(changeInRealMouse); + auto newReticlePosition = _reticlePositionInHMD + toGlm(changeInRealMouse); setReticlePosition(newReticlePosition, sendFakeEvent); _ignoreMouseMove = true; QCursor::setPos(QPoint(_lastKnownRealMouse.x(), _lastKnownRealMouse.y())); // move cursor back to where it was @@ -371,6 +371,7 @@ bool ApplicationCompositor::handleRealMouseMoveEvent(bool sendFakeEvent) { glm::vec2 ApplicationCompositor::getReticlePosition() { if (qApp->isHMDMode()) { + QMutexLocker locker(&_reticlePositionInHMDLock); return _reticlePositionInHMD; } return toGlm(QCursor::pos()); @@ -378,6 +379,8 @@ glm::vec2 ApplicationCompositor::getReticlePosition() { void ApplicationCompositor::setReticlePosition(glm::vec2 position, bool sendFakeEvent) { if (qApp->isHMDMode()) { + QMutexLocker locker(&_reticlePositionInHMDLock); + const float MOUSE_EXTENTS_VERT_ANGULAR_SIZE = 170.0f; // 5deg from poles const float MOUSE_EXTENTS_VERT_PIXELS = VIRTUAL_SCREEN_SIZE_Y * (MOUSE_EXTENTS_VERT_ANGULAR_SIZE / DEFAULT_HMD_UI_VERT_ANGULAR_SIZE); const float MOUSE_EXTENTS_HORZ_ANGULAR_SIZE = 360.0f; // full sphere @@ -390,12 +393,11 @@ void ApplicationCompositor::setReticlePosition(glm::vec2 position, bool sendFake glm::vec2 minMouse = vec2(0) - mouseExtra; glm::vec2 maxMouse = maxOverlayPosition + mouseExtra; - auto reticlePositionInHMD = glm::clamp(position, minMouse, maxMouse); - _reticlePositionInHMD.store(reticlePositionInHMD); + _reticlePositionInHMD = glm::clamp(position, minMouse, maxMouse); if (sendFakeEvent) { // in HMD mode we need to fake our mouse moves... - QPoint globalPos(reticlePositionInHMD.x, reticlePositionInHMD.y); + QPoint globalPos(_reticlePositionInHMD.x, _reticlePositionInHMD.y); auto button = Qt::NoButton; auto buttons = QApplication::mouseButtons(); auto modifiers = QApplication::keyboardModifiers(); diff --git a/interface/src/ui/ApplicationCompositor.h b/interface/src/ui/ApplicationCompositor.h index 672915d58d..94244e5586 100644 --- a/interface/src/ui/ApplicationCompositor.h +++ b/interface/src/ui/ApplicationCompositor.h @@ -146,7 +146,9 @@ private: // NOTE: when the compositor is running in HMD mode, it will control the reticle position as a custom // application specific position, when it's in desktop mode, the reticle position will simply move // the system mouse. - std::atomic _reticlePositionInHMD; + glm::vec2 _reticlePositionInHMD { 0.0f, 0.0f }; + mutable QMutex _reticlePositionInHMDLock{ QMutex::Recursive }; + QPointF _lastKnownRealMouse; bool _ignoreMouseMove { false }; From ba36eed9eb362d1a8f61c0544aa56c5728fd092a Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Sun, 21 Feb 2016 11:40:15 -0800 Subject: [PATCH 72/72] whitespace fixes --- interface/src/ui/ApplicationCompositor.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 8f8b97a2e1..a2fe95d649 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -300,7 +300,7 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int QPointF ApplicationCompositor::getMouseEventPosition(QMouseEvent* event) { if (qApp->isHMDMode()) { - QMutexLocker locker(&_reticlePositionInHMDLock); + QMutexLocker locker(&_reticlePositionInHMDLock); return QPointF(_reticlePositionInHMD.x, _reticlePositionInHMD.y); } return event->localPos(); @@ -355,7 +355,6 @@ bool ApplicationCompositor::handleRealMouseMoveEvent(bool sendFakeEvent) { // If we're in HMD mode if (shouldCaptureMouse()) { QMutexLocker locker(&_reticlePositionInHMDLock); - auto newPosition = QCursor::pos(); auto changeInRealMouse = newPosition - _lastKnownRealMouse; auto newReticlePosition = _reticlePositionInHMD + toGlm(changeInRealMouse); @@ -380,7 +379,6 @@ glm::vec2 ApplicationCompositor::getReticlePosition() { void ApplicationCompositor::setReticlePosition(glm::vec2 position, bool sendFakeEvent) { if (qApp->isHMDMode()) { QMutexLocker locker(&_reticlePositionInHMDLock); - const float MOUSE_EXTENTS_VERT_ANGULAR_SIZE = 170.0f; // 5deg from poles const float MOUSE_EXTENTS_VERT_PIXELS = VIRTUAL_SCREEN_SIZE_Y * (MOUSE_EXTENTS_VERT_ANGULAR_SIZE / DEFAULT_HMD_UI_VERT_ANGULAR_SIZE); const float MOUSE_EXTENTS_HORZ_ANGULAR_SIZE = 360.0f; // full sphere