From 0fac1e134f1fb0a66a1a8d6b54785646f56e7039 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Mon, 30 Sep 2019 16:43:02 -0700 Subject: [PATCH 01/11] Allow avatar look at when in first person camera --- interface/src/Application.cpp | 17 ++++------ interface/src/avatar/MyAvatar.cpp | 53 ++++++++++++++++++++++--------- interface/src/avatar/MyAvatar.h | 1 + 3 files changed, 46 insertions(+), 25 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6a320e53ee..7c08f7d978 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3601,10 +3601,9 @@ void Application::updateCamera(RenderArgs& renderArgs, float deltaTime) { mat4 camMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix(); _myCamera.setPosition(extractTranslation(camMat)); _myCamera.setOrientation(glmExtractRotation(camMat)); - } - else { - _myCamera.setPosition(myAvatar->getDefaultEyePosition()); - _myCamera.setOrientation(myAvatar->getMyHead()->getHeadOrientation()); + } else { + _myCamera.setPosition(myAvatar->getLookAtPivotPoint()); + _myCamera.setOrientation(myAvatar->getLookAtRotation()); } } else if (mode == CAMERA_MODE_THIRD_PERSON || mode == CAMERA_MODE_LOOK_AT || mode == CAMERA_MODE_SELFIE) { if (isHMDMode()) { @@ -3638,9 +3637,9 @@ void Application::updateCamera(RenderArgs& renderArgs, float deltaTime) { if (mode == CAMERA_MODE_SELFIE) { lookAtRotation = lookAtRotation * glm::angleAxis(PI, myAvatar->getWorldOrientation() * Vectors::UP); } - _myCamera.setPosition(myAvatar->getDefaultEyePosition() + _myCamera.setPosition(myAvatar->getLookAtPivotPoint() + lookAtRotation * boomOffset); - _myCamera.lookAt(myAvatar->getDefaultEyePosition()); + _myCamera.lookAt(myAvatar->getLookAtPivotPoint()); } } } else if (mode == CAMERA_MODE_MIRROR) { @@ -3668,8 +3667,7 @@ void Application::updateCamera(RenderArgs& renderArgs, float deltaTime) { + glm::vec3(0, _raiseMirror * myAvatar->getModelScale(), 0) + mirrorBodyOrientation * glm::vec3(0.0f, 0.0f, 1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror + mirrorBodyOrientation * hmdOffset); - } - else { + } else { auto userInputMapper = DependencyManager::get(); const float YAW_SPEED = TWO_PI / 5.0f; float deltaYaw = userInputMapper->getActionState(controller::Action::YAW) * YAW_SPEED * deltaTime; @@ -3690,8 +3688,7 @@ void Application::updateCamera(RenderArgs& renderArgs, float deltaTime) { _myCamera.setOrientation(cameraEntity->getWorldOrientation() * hmdRotation); glm::vec3 hmdOffset = extractTranslation(myAvatar->getHMDSensorMatrix()); _myCamera.setPosition(cameraEntity->getWorldPosition() + (hmdRotation * hmdOffset)); - } - else { + } else { _myCamera.setOrientation(cameraEntity->getWorldOrientation()); _myCamera.setPosition(cameraEntity->getWorldPosition()); } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 6f16e6e1bf..8728c2bd80 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -953,7 +953,7 @@ void MyAvatar::simulate(float deltaTime, bool inView) { head->setScale(getModelScale()); head->simulate(deltaTime); CameraMode mode = qApp->getCamera().getMode(); - if (_scriptControlsHeadLookAt || mode == CAMERA_MODE_LOOK_AT || mode == CAMERA_MODE_SELFIE) { + if (_scriptControlsHeadLookAt || mode == CAMERA_MODE_FIRST_PERSON || mode == CAMERA_MODE_LOOK_AT || mode == CAMERA_MODE_SELFIE) { updateHeadLookAt(deltaTime); } else if (_headLookAtActive){ resetHeadLookAt(); @@ -3429,8 +3429,10 @@ void MyAvatar::updateOrientation(float deltaTime) { // Smoothly rotate body with arrow keys float targetSpeed = getDriveKey(YAW) * _yawSpeed; CameraMode mode = qApp->getCamera().getMode(); - bool computeLookAt = (mode == CAMERA_MODE_LOOK_AT || mode == CAMERA_MODE_SELFIE) && isReadyForPhysics() && !qApp->isHMDMode(); - if (computeLookAt) { + bool computeLookAt = isReadyForPhysics() && !qApp->isHMDMode() && + (mode == CAMERA_MODE_FIRST_PERSON || mode == CAMERA_MODE_LOOK_AT || mode == CAMERA_MODE_SELFIE); + bool smoothCameraYaw = computeLookAt && mode != CAMERA_MODE_FIRST_PERSON; + if (smoothCameraYaw) { // For "Look At" and "Selfie" camera modes we also smooth the yaw rotation from right-click mouse movement. float speedFromDeltaYaw = deltaTime > FLT_EPSILON ? getDriveKey(DELTA_YAW) / deltaTime : 0.0f; speedFromDeltaYaw *= _yawSpeed / YAW_SPEED_DEFAULT; @@ -3459,7 +3461,7 @@ void MyAvatar::updateOrientation(float deltaTime) { } } float totalBodyYaw = _bodyYawDelta * deltaTime; - if (!computeLookAt) { + if (!smoothCameraYaw) { // Rotate directly proportional to delta yaw and delta pitch from right-click mouse movement. totalBodyYaw += getDriveKey(DELTA_YAW) * _yawSpeed / YAW_SPEED_DEFAULT; } @@ -3546,12 +3548,16 @@ void MyAvatar::updateOrientation(float deltaTime) { blend = 1.0f; } glm::quat faceRotation = _lookAtYaw; - if (isMovingFwdBwd && isMovingSideways) { - // Reorient avatar to face camera diagonal - blend = DIAGONAL_TURN_BLEND; - float turnSign = getDriveKey(TRANSLATE_Z) < 0.0f ? -1.0f : 1.0f; - turnSign = getDriveKey(TRANSLATE_X) > 0.0f ? -turnSign : turnSign; - faceRotation = _lookAtYaw * glm::angleAxis(turnSign * 0.25f * PI, Vectors::UP); + if (isMovingFwdBwd) { + if (isMovingSideways) { + // Reorient avatar to face camera diagonal + blend = mode == CAMERA_MODE_FIRST_PERSON ? 1.0f : DIAGONAL_TURN_BLEND; + float turnSign = getDriveKey(TRANSLATE_Z) < 0.0f ? -1.0f : 1.0f; + turnSign = getDriveKey(TRANSLATE_X) > 0.0f ? -turnSign : turnSign; + faceRotation = _lookAtYaw * glm::angleAxis(turnSign * 0.25f * PI, Vectors::UP); + } else if (mode == CAMERA_MODE_FIRST_PERSON) { + blend = 1.0f; + } } setWorldOrientation(glm::slerp(getWorldOrientation(), faceRotation, blend)); } else if (isRotatingWhileSeated) { @@ -3615,11 +3621,21 @@ void MyAvatar::updateOrientation(float deltaTime) { const float REORIENT_ANGLE = 65.0f; const float TRIGGER_REORIENT_ANGLE = 45.0f; + const float FIRST_PERSON_TRIGGER_REORIENT_ANGLE = 45.0f; glm::vec3 ajustedYawVector = cameraYawVector; - if (frontBackDot < 0.0f) { - ajustedYawVector = (leftRightDot < 0.0f ? -avatarVectorRight : avatarVectorRight); - cameraVector = (ajustedYawVector * _lookAtPitch) * Vectors::FRONT; - if (frontBackDot < -glm::sin(glm::radians(TRIGGER_REORIENT_ANGLE))) { + float limitAngle = 0.0f; + float triggerAngle = -glm::sin(glm::radians(TRIGGER_REORIENT_ANGLE)); + if (mode == CAMERA_MODE_FIRST_PERSON) { + limitAngle = glm::sin(glm::radians(FIRST_PERSON_TRIGGER_REORIENT_ANGLE)); + triggerAngle = limitAngle; + } + + if (frontBackDot < limitAngle) { + if (frontBackDot < 0.0f) { + ajustedYawVector = (leftRightDot < 0.0f ? -avatarVectorRight : avatarVectorRight); + cameraVector = (ajustedYawVector * _lookAtPitch) * Vectors::FRONT; + } + if (frontBackDot < triggerAngle) { _shouldTurnToFaceCamera = true; } } else if (frontBackDot > glm::sin(glm::radians(REORIENT_ANGLE))) { @@ -3716,7 +3732,8 @@ glm::vec3 MyAvatar::scaleMotorSpeed(const glm::vec3 forward, const glm::vec3 rig } else { // Desktop mode. direction = (zSpeed * forward) + (xSpeed * right); - if (qApp->getCamera().getMode() == CAMERA_MODE_LOOK_AT && zSpeed != 0.0f && xSpeed != 0.0f){ + CameraMode mode = qApp->getCamera().getMode(); + if ((mode == CAMERA_MODE_LOOK_AT || mode == CAMERA_MODE_FIRST_PERSON || mode == CAMERA_MODE_SELFIE) && zSpeed != 0.0f && xSpeed != 0.0f){ direction = (zSpeed * forward); } @@ -6732,3 +6749,9 @@ void MyAvatar::setHeadLookAt(const glm::vec3& lookAtTarget) { _scriptHeadControlTimer = 0.0f; _lookAtScriptTarget = lookAtTarget; } + +glm::vec3 MyAvatar::getLookAtPivotPoint() { + glm::vec3 avatarUp = getWorldOrientation() * Vectors::UP; + glm::vec3 yAxisEyePosition = getWorldPosition() + avatarUp * glm::dot(avatarUp, _skeletonModel->getDefaultEyeModelPosition()); + return yAxisEyePosition; +} \ No newline at end of file diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 7b63e8e86b..6f90af7ece 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -1896,6 +1896,7 @@ public: void debugDrawPose(controller::Action action, const char* channelName, float size); bool getIsJointOverridden(int jointIndex) const; + glm::vec3 getLookAtPivotPoint(); public slots: From 595b473be79ca7d2b6e7a0e0f74d0251528f1675 Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Mon, 30 Sep 2019 17:55:24 -0700 Subject: [PATCH 02/11] Make AssetScriptingInterface::initializeCache() blocking --- .../src/AssetScriptingInterface.cpp | 19 +++++++++++++++++++ .../src/AssetScriptingInterface.h | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/libraries/script-engine/src/AssetScriptingInterface.cpp b/libraries/script-engine/src/AssetScriptingInterface.cpp index 54b570e256..84fefece93 100644 --- a/libraries/script-engine/src/AssetScriptingInterface.cpp +++ b/libraries/script-engine/src/AssetScriptingInterface.cpp @@ -38,6 +38,25 @@ AssetScriptingInterface::AssetScriptingInterface(QObject* parent) : BaseAssetScr #define JS_VERIFY(cond, error) { if (!this->jsVerify(cond, error)) { return; } } +bool AssetScriptingInterface::initializeCache() { + if (!Parent::initializeCache()) { + if (assetClient()) { + std::promise cacheStatusResult; + Promise assetClientPromise(makePromise(__func__)); + assetClientPromise->moveToThread(qApp->thread()); // To ensure the finally() is processed. + + assetClient()->cacheInfoRequestAsync(assetClientPromise); + assetClientPromise->finally([&](QString, QVariantMap result) + { cacheStatusResult.set_value(!result.isEmpty()); }); + return cacheStatusResult.get_future().get(); + } else { + return false; + } + } else { + return true; + } +} + void AssetScriptingInterface::uploadData(QString data, QScriptValue callback) { auto handler = jsBindCallback(thisObject(), callback); QByteArray dataByteArray = data.toUtf8(); diff --git a/libraries/script-engine/src/AssetScriptingInterface.h b/libraries/script-engine/src/AssetScriptingInterface.h index 5da3c51a08..955adaa86c 100644 --- a/libraries/script-engine/src/AssetScriptingInterface.h +++ b/libraries/script-engine/src/AssetScriptingInterface.h @@ -356,7 +356,7 @@ public: * @function Assets.initializeCache * @returns {boolean} true if the cache is initialized, false if it isn't. */ - Q_INVOKABLE bool initializeCache() { return Parent::initializeCache(); } + Q_INVOKABLE bool initializeCache(); /**jsdoc * Checks whether the script can write to the cache. From 95248c7ccdd4c5fe2d8ef77e6b770d1e4a85ad21 Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Mon, 30 Sep 2019 23:43:06 -0700 Subject: [PATCH 03/11] Add header for Android --- libraries/script-engine/src/AssetScriptingInterface.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/script-engine/src/AssetScriptingInterface.cpp b/libraries/script-engine/src/AssetScriptingInterface.cpp index 84fefece93..33be9de2ad 100644 --- a/libraries/script-engine/src/AssetScriptingInterface.cpp +++ b/libraries/script-engine/src/AssetScriptingInterface.cpp @@ -29,6 +29,8 @@ #include #include +#include + using Promise = MiniPromise::Promise; AssetScriptingInterface::AssetScriptingInterface(QObject* parent) : BaseAssetScriptingInterface(parent) { From 18af7c5d84771ed67939ffac518efc24ff6eeae3 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Tue, 1 Oct 2019 13:44:27 -0700 Subject: [PATCH 04/11] Add recenter timer and temp API --- interface/src/avatar/MyAvatar.cpp | 56 +++++++++++++++++++++++++++---- interface/src/avatar/MyAvatar.h | 7 ++++ 2 files changed, 57 insertions(+), 6 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 8728c2bd80..ac762dcc44 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -3619,17 +3619,18 @@ void MyAvatar::updateOrientation(float deltaTime) { glm::vec3 avatarVectorRight = getWorldOrientation() * Vectors::RIGHT; float leftRightDot = glm::dot(cameraYawVector, avatarVectorRight); - const float REORIENT_ANGLE = 65.0f; + const float DEFAULT_REORIENT_ANGLE = 65.0f; + const float FIRST_PERSON_REORIENT_ANGLE = 95.0f; const float TRIGGER_REORIENT_ANGLE = 45.0f; - const float FIRST_PERSON_TRIGGER_REORIENT_ANGLE = 45.0f; + // const float FIRST_PERSON_TRIGGER_REORIENT_ANGLE = 45.0f; glm::vec3 ajustedYawVector = cameraYawVector; float limitAngle = 0.0f; float triggerAngle = -glm::sin(glm::radians(TRIGGER_REORIENT_ANGLE)); if (mode == CAMERA_MODE_FIRST_PERSON) { - limitAngle = glm::sin(glm::radians(FIRST_PERSON_TRIGGER_REORIENT_ANGLE)); + limitAngle = glm::sin(glm::radians(90.0f - _recenterAngle)); triggerAngle = limitAngle; } - + float reorientAngle = mode == CAMERA_MODE_FIRST_PERSON ? FIRST_PERSON_REORIENT_ANGLE : DEFAULT_REORIENT_ANGLE; if (frontBackDot < limitAngle) { if (frontBackDot < 0.0f) { ajustedYawVector = (leftRightDot < 0.0f ? -avatarVectorRight : avatarVectorRight); @@ -3637,8 +3638,9 @@ void MyAvatar::updateOrientation(float deltaTime) { } if (frontBackDot < triggerAngle) { _shouldTurnToFaceCamera = true; + _firstPersonSteadyHeadTimer = 0.0f; } - } else if (frontBackDot > glm::sin(glm::radians(REORIENT_ANGLE))) { + } else if (frontBackDot > glm::sin(glm::radians(reorientAngle))) { _shouldTurnToFaceCamera = false; } @@ -3660,6 +3662,22 @@ void MyAvatar::updateOrientation(float deltaTime) { _lookAtCameraTarget = targetPoint; } _headLookAtActive = true; + // const float FIRST_PERSON_RECENTER_SECONDS = 5.0f; + if (mode == CAMERA_MODE_FIRST_PERSON) { + if (getDriveKey(YAW) + getDriveKey(STEP_YAW) + getDriveKey(DELTA_YAW) == 0.0f) { + if (_firstPersonSteadyHeadTimer < _recenterSeconds) { + if (_firstPersonSteadyHeadTimer > 0.0f) { + _firstPersonSteadyHeadTimer += deltaTime; + } + } else { + _shouldTurnToFaceCamera = true; + _firstPersonSteadyHeadTimer = 0.0f; + } + } else { + _firstPersonSteadyHeadTimer = deltaTime; + } + } + } else { head->setBaseYaw(0.0f); head->setBasePitch(getHead()->getBasePitch() + getDriveKey(PITCH) * _pitchSpeed * deltaTime @@ -6754,4 +6772,30 @@ glm::vec3 MyAvatar::getLookAtPivotPoint() { glm::vec3 avatarUp = getWorldOrientation() * Vectors::UP; glm::vec3 yAxisEyePosition = getWorldPosition() + avatarUp * glm::dot(avatarUp, _skeletonModel->getDefaultEyeModelPosition()); return yAxisEyePosition; -} \ No newline at end of file +} + +QVariantMap MyAvatar::getLookAtCameraData() { + QVariantMap result; + if (QThread::currentThread() != thread()) { + BLOCKING_INVOKE_METHOD(this, "getLookAtCameraData", + Q_RETURN_ARG(QVariantMap, result)); + return result; + } + result.insert("recenterSeconds", _recenterSeconds); + result.insert("recenterAngle", _recenterAngle); + return result; +} + +Q_INVOKABLE void MyAvatar::setLookAtCameraData(const QVariantMap& data) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "setLookAtCameraData", + Q_ARG(const QVariantMap&, data)); + return; + } + if (data.contains("recenterSeconds")) { + _recenterSeconds = data["recenterSeconds"].toFloat(); + } + if (data.contains("recenterAngle")) { + _recenterAngle = data["recenterAngle"].toFloat(); + } +} diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 6f90af7ece..c3a2f76f70 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -1857,6 +1857,9 @@ public: */ Q_INVOKABLE QVariantMap getFlowData(); + Q_INVOKABLE QVariantMap getLookAtCameraData(); + Q_INVOKABLE void setLookAtCameraData(const QVariantMap& data); + /**jsdoc * Gets the indexes of currently colliding flow joints. * @function MyAvatar.getCollidingFlowJoints @@ -2654,6 +2657,10 @@ private: bool _shouldTurnToFaceCamera { false }; bool _scriptControlsHeadLookAt { false }; float _scriptHeadControlTimer { 0.0f }; + float _firstPersonSteadyHeadTimer { 0.0f }; + + float _recenterSeconds { 5.0f }; + float _recenterAngle { 45.0f }; Setting::Handle _realWorldFieldOfView; Setting::Handle _useAdvancedMovementControls; From d0cb48924709cfb4002f7110799d616b52018086 Mon Sep 17 00:00:00 2001 From: Roxanne Skelly Date: Tue, 1 Oct 2019 15:34:39 -0700 Subject: [PATCH 05/11] DEV-1836 - handle urls in the form 'hifi://: --- libraries/networking/src/AddressManager.cpp | 47 ++++++++++++--------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index bd3dc7c177..973d8a625b 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -234,14 +234,33 @@ const JSONCallbackParameters& AddressManager::apiCallbackParameters() { return callbackParams; } -bool AddressManager::handleUrl(const QUrl& lookupUrl, LookupTrigger trigger) { +bool AddressManager::handleUrl(const QUrl& lookupUrlIn, LookupTrigger trigger) { static QString URL_TYPE_USER = "user"; static QString URL_TYPE_DOMAIN_ID = "domain_id"; static QString URL_TYPE_PLACE = "place"; static QString URL_TYPE_NETWORK_ADDRESS = "network_address"; - if (lookupUrl.scheme() == URL_SCHEME_HIFI) { - qCDebug(networking) << "Trying to go to URL" << lookupUrl.toString(); + QUrl lookupUrl = lookupUrlIn; + + qCDebug(networking) << "Trying to go to URL" << lookupUrl.toString(); + + if (lookupUrl.scheme().isEmpty() && !lookupUrl.path().startsWith("/")) { + // 'urls' without schemes are taken as domain names, as opposed to + // simply a path portion of a url, so we need to set the scheme + lookupUrl.setScheme(URL_SCHEME_HIFI); + } + + // it should be noted that url's in the form + // somewhere: are not valid, as that + // would indicate that the scheme is 'somewhere' + // use hifi://somewhere: instead + + if (lookupUrl.scheme() == URL_SCHEME_HIFI) { + if (lookupUrl.host().isEmpty()) { + // this was in the form hifi:/somewhere or hifi:somewhere. Fix it by making it hifi://somewhere + const QRegExp HIFI_SCHEME_REGEX = QRegExp(URL_SCHEME_HIFI + ":\\/?", Qt::CaseInsensitive); + lookupUrl = QUrl(lookupUrl.toString().replace(HIFI_SCHEME_REGEX, URL_SCHEME_HIFI + "://")); + } DependencyManager::get()->flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::LookupAddress); @@ -379,25 +398,11 @@ bool isPossiblePlaceName(QString possiblePlaceName) { } void AddressManager::handleLookupString(const QString& lookupString, bool fromSuggestions) { - if (!lookupString.isEmpty()) { + + QString sanitizedString = lookupString.trimmed(); + if (!sanitizedString.isEmpty()) { // make this a valid hifi URL and handle it off to handleUrl - QString sanitizedString = lookupString.trimmed(); - QUrl lookupURL; - - if (!lookupString.startsWith('/')) { - // sometimes we need to handle lookupStrings like hifi:/somewhere - const QRegExp HIFI_SCHEME_REGEX = QRegExp(URL_SCHEME_HIFI + ":\\/{1,2}", Qt::CaseInsensitive); - sanitizedString = sanitizedString.remove(HIFI_SCHEME_REGEX); - - lookupURL = QUrl(sanitizedString); - if (lookupURL.scheme().isEmpty() || lookupURL.scheme().toLower() == LOCALHOST) { - lookupURL = QUrl("hifi://" + sanitizedString); - } - } else { - lookupURL = QUrl(sanitizedString); - } - - handleUrl(lookupURL, fromSuggestions ? Suggestions : UserInput); + handleUrl(sanitizedString, fromSuggestions ? Suggestions : UserInput); } } From 9af7b904abb0df0633d091b423189152ca0fe0e7 Mon Sep 17 00:00:00 2001 From: Roxanne Skelly Date: Tue, 1 Oct 2019 17:04:07 -0700 Subject: [PATCH 06/11] CR related fixes --- libraries/networking/src/AddressManager.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 973d8a625b..828396d9d7 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -250,6 +250,11 @@ bool AddressManager::handleUrl(const QUrl& lookupUrlIn, LookupTrigger trigger) { lookupUrl.setScheme(URL_SCHEME_HIFI); } + static const QRegExp PORT_REGEX = QRegExp("\\d{1,5}"); + if(!lookupUrl.scheme().isEmpty() && lookupUrl.host().isEmpty() && PORT_REGEX.exactMatch(lookupUrl.path())) { + // this is in the form somewhere:, convert it to hifi://somewhere: + lookupUrl = QUrl(URL_SCHEME_HIFI + "://" + lookupUrl.toString()); + } // it should be noted that url's in the form // somewhere: are not valid, as that // would indicate that the scheme is 'somewhere' @@ -258,7 +263,7 @@ bool AddressManager::handleUrl(const QUrl& lookupUrlIn, LookupTrigger trigger) { if (lookupUrl.scheme() == URL_SCHEME_HIFI) { if (lookupUrl.host().isEmpty()) { // this was in the form hifi:/somewhere or hifi:somewhere. Fix it by making it hifi://somewhere - const QRegExp HIFI_SCHEME_REGEX = QRegExp(URL_SCHEME_HIFI + ":\\/?", Qt::CaseInsensitive); + static const QRegExp HIFI_SCHEME_REGEX = QRegExp(URL_SCHEME_HIFI + ":\\/?", Qt::CaseInsensitive); lookupUrl = QUrl(lookupUrl.toString().replace(HIFI_SCHEME_REGEX, URL_SCHEME_HIFI + "://")); } From 521aa50356c9077a5364c7926a651aba3c8eda93 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Wed, 2 Oct 2019 11:43:06 -0700 Subject: [PATCH 07/11] Set time and angle recentering parameters --- interface/src/avatar/MyAvatar.cpp | 33 ++++--------------------------- interface/src/avatar/MyAvatar.h | 6 ------ 2 files changed, 4 insertions(+), 35 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index ac762dcc44..4f6bd616b4 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -3622,12 +3622,12 @@ void MyAvatar::updateOrientation(float deltaTime) { const float DEFAULT_REORIENT_ANGLE = 65.0f; const float FIRST_PERSON_REORIENT_ANGLE = 95.0f; const float TRIGGER_REORIENT_ANGLE = 45.0f; - // const float FIRST_PERSON_TRIGGER_REORIENT_ANGLE = 45.0f; + const float FIRST_PERSON_TRIGGER_REORIENT_ANGLE = 65.0f; glm::vec3 ajustedYawVector = cameraYawVector; float limitAngle = 0.0f; float triggerAngle = -glm::sin(glm::radians(TRIGGER_REORIENT_ANGLE)); if (mode == CAMERA_MODE_FIRST_PERSON) { - limitAngle = glm::sin(glm::radians(90.0f - _recenterAngle)); + limitAngle = glm::sin(glm::radians(90.0f - FIRST_PERSON_TRIGGER_REORIENT_ANGLE)); triggerAngle = limitAngle; } float reorientAngle = mode == CAMERA_MODE_FIRST_PERSON ? FIRST_PERSON_REORIENT_ANGLE : DEFAULT_REORIENT_ANGLE; @@ -3662,10 +3662,10 @@ void MyAvatar::updateOrientation(float deltaTime) { _lookAtCameraTarget = targetPoint; } _headLookAtActive = true; - // const float FIRST_PERSON_RECENTER_SECONDS = 5.0f; + const float FIRST_PERSON_RECENTER_SECONDS = 15.0f; if (mode == CAMERA_MODE_FIRST_PERSON) { if (getDriveKey(YAW) + getDriveKey(STEP_YAW) + getDriveKey(DELTA_YAW) == 0.0f) { - if (_firstPersonSteadyHeadTimer < _recenterSeconds) { + if (_firstPersonSteadyHeadTimer < FIRST_PERSON_RECENTER_SECONDS) { if (_firstPersonSteadyHeadTimer > 0.0f) { _firstPersonSteadyHeadTimer += deltaTime; } @@ -6774,28 +6774,3 @@ glm::vec3 MyAvatar::getLookAtPivotPoint() { return yAxisEyePosition; } -QVariantMap MyAvatar::getLookAtCameraData() { - QVariantMap result; - if (QThread::currentThread() != thread()) { - BLOCKING_INVOKE_METHOD(this, "getLookAtCameraData", - Q_RETURN_ARG(QVariantMap, result)); - return result; - } - result.insert("recenterSeconds", _recenterSeconds); - result.insert("recenterAngle", _recenterAngle); - return result; -} - -Q_INVOKABLE void MyAvatar::setLookAtCameraData(const QVariantMap& data) { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "setLookAtCameraData", - Q_ARG(const QVariantMap&, data)); - return; - } - if (data.contains("recenterSeconds")) { - _recenterSeconds = data["recenterSeconds"].toFloat(); - } - if (data.contains("recenterAngle")) { - _recenterAngle = data["recenterAngle"].toFloat(); - } -} diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index c3a2f76f70..e099ab0dbe 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -1857,9 +1857,6 @@ public: */ Q_INVOKABLE QVariantMap getFlowData(); - Q_INVOKABLE QVariantMap getLookAtCameraData(); - Q_INVOKABLE void setLookAtCameraData(const QVariantMap& data); - /**jsdoc * Gets the indexes of currently colliding flow joints. * @function MyAvatar.getCollidingFlowJoints @@ -2659,9 +2656,6 @@ private: float _scriptHeadControlTimer { 0.0f }; float _firstPersonSteadyHeadTimer { 0.0f }; - float _recenterSeconds { 5.0f }; - float _recenterAngle { 45.0f }; - Setting::Handle _realWorldFieldOfView; Setting::Handle _useAdvancedMovementControls; Setting::Handle _showPlayArea; From 6bfca4e58730a40572af186bb8bee8135abefd5d Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 2 Oct 2019 11:48:50 -0700 Subject: [PATCH 08/11] DEV-2275: Move 'input device muted' banner and make it slightly smaller --- scripts/simplifiedUI/ui/simplifiedUI.js | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/scripts/simplifiedUI/ui/simplifiedUI.js b/scripts/simplifiedUI/ui/simplifiedUI.js index f1f1dd6dd3..1154e386ea 100644 --- a/scripts/simplifiedUI/ui/simplifiedUI.js +++ b/scripts/simplifiedUI/ui/simplifiedUI.js @@ -296,7 +296,7 @@ function updateOutputDeviceMutedOverlay(isMuted) { props.y = Window.innerHeight / 2 - overlayDims / 2; var outputDeviceMutedOverlayBottomY = props.y + overlayDims; - var inputDeviceMutedOverlayTopY = getInputDeviceMutedOverlayTopY(); + var inputDeviceMutedOverlayTopY = INPUT_DEVICE_MUTED_MARGIN_TOP_PX; if (outputDeviceMutedOverlayBottomY + OUTPUT_DEVICE_MUTED_MARGIN_BOTTOM_PX > inputDeviceMutedOverlayTopY) { overlayDims = 2 * (inputDeviceMutedOverlayTopY - Window.innerHeight / 2 - OUTPUT_DEVICE_MUTED_MARGIN_BOTTOM_PX); } @@ -473,15 +473,11 @@ function maybeDeleteInputDeviceMutedOverlay() { } -function getInputDeviceMutedOverlayTopY() { - return (Window.innerHeight - INPUT_DEVICE_MUTED_OVERLAY_DEFAULT_Y_PX - INPUT_DEVICE_MUTED_MARGIN_BOTTOM_PX); -} - - var inputDeviceMutedOverlay = false; -var INPUT_DEVICE_MUTED_OVERLAY_DEFAULT_X_PX = 353; -var INPUT_DEVICE_MUTED_OVERLAY_DEFAULT_Y_PX = 95; -var INPUT_DEVICE_MUTED_MARGIN_BOTTOM_PX = 20 + TOP_BAR_HEIGHT_PX; +var INPUT_DEVICE_MUTED_OVERLAY_DEFAULT_X_PX = 237; +var INPUT_DEVICE_MUTED_OVERLAY_DEFAULT_Y_PX = 64; +var INPUT_DEVICE_MUTED_MARGIN_LEFT_PX = 20; +var INPUT_DEVICE_MUTED_MARGIN_TOP_PX = 20; function updateInputDeviceMutedOverlay(isMuted) { if (isMuted) { var props = { @@ -490,8 +486,8 @@ function updateInputDeviceMutedOverlay(isMuted) { }; props.width = INPUT_DEVICE_MUTED_OVERLAY_DEFAULT_X_PX; props.height = INPUT_DEVICE_MUTED_OVERLAY_DEFAULT_Y_PX; - props.x = Window.innerWidth / 2 - INPUT_DEVICE_MUTED_OVERLAY_DEFAULT_X_PX / 2; - props.y = getInputDeviceMutedOverlayTopY(); + props.x = INPUT_DEVICE_MUTED_MARGIN_LEFT_PX; + props.y = INPUT_DEVICE_MUTED_MARGIN_TOP_PX; if (inputDeviceMutedOverlay) { Overlays.editOverlay(inputDeviceMutedOverlay, props); } else { From 75f0b4ea54c84f85dff2c3e28196d42eef94515c Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Wed, 2 Oct 2019 14:17:57 -0700 Subject: [PATCH 09/11] Fix First Person Camera issues --- interface/src/avatar/MyAvatar.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 090694b639..7af563608d 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2718,7 +2718,8 @@ void MyAvatar::updateMotors() { if (_motionBehaviors & AVATAR_MOTION_ACTION_MOTOR_ENABLED) { if (_characterController.getState() == CharacterController::State::Hover || _characterController.computeCollisionMask() == BULLET_COLLISION_MASK_COLLISIONLESS) { - if (qApp->getCamera().getMode() == CAMERA_MODE_LOOK_AT || qApp->getCamera().getMode() == CAMERA_MODE_SELFIE) { + CameraMode mode = qApp->getCamera().getMode(); + if (mode == CAMERA_MODE_FIRST_PERSON || mode == CAMERA_MODE_LOOK_AT || mode == CAMERA_MODE_SELFIE) { motorRotation = getLookAtRotation(); } else { motorRotation = getMyHead()->getHeadOrientation(); @@ -5434,7 +5435,7 @@ glm::quat MyAvatar::getOrientationForAudio() { case AudioListenerMode::FROM_HEAD: { // Using the camera's orientation instead, when the current mode is controlling the avatar's head. CameraMode mode = qApp->getCamera().getMode(); - bool headFollowsCamera = mode == CAMERA_MODE_LOOK_AT || mode == CAMERA_MODE_SELFIE; + bool headFollowsCamera = mode == CAMERA_MODE_FIRST_PERSON || mode == CAMERA_MODE_LOOK_AT || mode == CAMERA_MODE_SELFIE; result = headFollowsCamera ? qApp->getCamera().getOrientation() : getHead()->getFinalOrientationInWorldFrame(); break; } From fb8a0e3aee9f3f372d3d6784a3f52223890de938 Mon Sep 17 00:00:00 2001 From: Roxanne Skelly Date: Wed, 2 Oct 2019 16:40:27 -0700 Subject: [PATCH 10/11] handle urls in the form of :/path --- libraries/networking/src/AddressManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 828396d9d7..50e2657622 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -250,7 +250,7 @@ bool AddressManager::handleUrl(const QUrl& lookupUrlIn, LookupTrigger trigger) { lookupUrl.setScheme(URL_SCHEME_HIFI); } - static const QRegExp PORT_REGEX = QRegExp("\\d{1,5}"); + static const QRegExp PORT_REGEX = QRegExp("\\d{1,5}(\\/.*)?"); if(!lookupUrl.scheme().isEmpty() && lookupUrl.host().isEmpty() && PORT_REGEX.exactMatch(lookupUrl.path())) { // this is in the form somewhere:, convert it to hifi://somewhere: lookupUrl = QUrl(URL_SCHEME_HIFI + "://" + lookupUrl.toString()); From f7a5895cf3560f006c68f2926a44104f225f5d1a Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Thu, 3 Oct 2019 14:42:58 -0700 Subject: [PATCH 11/11] Apply same random factors to both eyes blink --- libraries/avatars-renderer/src/avatars-renderer/Head.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp index 445184f5f8..63d8e2981c 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp @@ -92,22 +92,23 @@ void Head::simulate(float deltaTime) { } else if (_timeWithoutTalking - deltaTime < BLINK_AFTER_TALKING && _timeWithoutTalking >= BLINK_AFTER_TALKING) { forceBlink = true; } - if (_leftEyeBlinkVelocity == 0.0f && _rightEyeBlinkVelocity == 0.0f) { // no blinking when brows are raised; blink less with increasing loudness const float BASE_BLINK_RATE = 15.0f / 60.0f; const float ROOT_LOUDNESS_TO_BLINK_INTERVAL = 0.25f; if (forceBlink || (_browAudioLift < EPSILON && shouldDo(glm::max(1.0f, sqrt(fabs(_averageLoudness - _longTermAverageLoudness)) * ROOT_LOUDNESS_TO_BLINK_INTERVAL) / BASE_BLINK_RATE, deltaTime))) { - _leftEyeBlinkVelocity = BLINK_SPEED + randFloat() * BLINK_SPEED_VARIABILITY; - _rightEyeBlinkVelocity = BLINK_SPEED + randFloat() * BLINK_SPEED_VARIABILITY; + float randSpeedVariability = randFloat(); + float eyeBlinkVelocity = BLINK_SPEED + randSpeedVariability * BLINK_SPEED_VARIABILITY; + _leftEyeBlinkVelocity = eyeBlinkVelocity; + _rightEyeBlinkVelocity = eyeBlinkVelocity; if (randFloat() < 0.5f) { _leftEyeBlink = BLINK_START_VARIABILITY; - } else { _rightEyeBlink = BLINK_START_VARIABILITY; } } } else { + _leftEyeBlink = glm::clamp(_leftEyeBlink + _leftEyeBlinkVelocity * deltaTime, FULLY_OPEN, FULLY_CLOSED); _rightEyeBlink = glm::clamp(_rightEyeBlink + _rightEyeBlinkVelocity * deltaTime, FULLY_OPEN, FULLY_CLOSED);