diff --git a/android/app/src/main/cpp/native.cpp b/android/app/src/main/cpp/native.cpp index 437505be3f..9b5e5f2543 100644 --- a/android/app/src/main/cpp/native.cpp +++ b/android/app/src/main/cpp/native.cpp @@ -228,7 +228,7 @@ Java_io_highfidelity_hifiinterface_fragment_LoginFragment_nativeLogin(JNIEnv *en env->ReleaseStringUTFChars(username_, c_username); env->ReleaseStringUTFChars(password_, c_password); - auto accountManager = AndroidHelper::instance().getAccountManager(); + auto accountManager = DependencyManager::get(); __loginCompletedListener = QAndroidJniObject(instance); __usernameChangedListener = QAndroidJniObject(usernameChangedListener); @@ -270,18 +270,18 @@ Java_io_highfidelity_hifiinterface_SplashActivity_registerLoadCompleteListener(J } JNIEXPORT jboolean JNICALL Java_io_highfidelity_hifiinterface_MainActivity_nativeIsLoggedIn(JNIEnv *env, jobject instance) { - return AndroidHelper::instance().getAccountManager()->isLoggedIn(); + return DependencyManager::get()->isLoggedIn(); } JNIEXPORT void JNICALL Java_io_highfidelity_hifiinterface_MainActivity_nativeLogout(JNIEnv *env, jobject instance) { - AndroidHelper::instance().getAccountManager()->logout(); + DependencyManager::get()->logout(); } JNIEXPORT jstring JNICALL Java_io_highfidelity_hifiinterface_MainActivity_nativeGetDisplayName(JNIEnv *env, jobject instance) { - QString username = AndroidHelper::instance().getAccountManager()->getAccountInfo().getUsername(); + QString username = DependencyManager::get()->getAccountInfo().getUsername(); return env->NewStringUTF(username.toLatin1().data()); } diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index 3ca8c1ecd1..8b86ba5eb2 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -504,6 +504,11 @@ void EntityServer::startDynamicDomainVerification() { QString thisDomainID = DependencyManager::get()->getDomainID().remove(QRegExp("\\{|\\}")); if (jsonObject["domain_id"].toString() != thisDomainID) { EntityItemPointer entity = tree->findEntityByEntityItemID(entityID); + if (!entity) { + qCDebug(entities) << "Entity undergoing dynamic domain verification is no longer available:" << entityID; + networkReply->deleteLater(); + return; + } if (entity->getAge() > (_MAXIMUM_DYNAMIC_DOMAIN_VERIFICATION_TIMER_MS/MSECS_PER_SECOND)) { qCDebug(entities) << "Entity's cert's domain ID" << jsonObject["domain_id"].toString() << "doesn't match the current Domain ID" << thisDomainID << "; deleting entity" << entityID; diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index b4685b907f..2a6b78744e 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -660,9 +660,8 @@ void DomainGatekeeper::requestUserPublicKey(const QString& username, bool isOpti // even if we have a public key for them right now, request a new one in case it has just changed JSONCallbackParameters callbackParams; - callbackParams.jsonCallbackReceiver = this; + callbackParams.callbackReceiver = this; callbackParams.jsonCallbackMethod = "publicKeyJSONCallback"; - callbackParams.errorCallbackReceiver = this; callbackParams.errorCallbackMethod = "publicKeyJSONErrorCallback"; @@ -675,19 +674,19 @@ void DomainGatekeeper::requestUserPublicKey(const QString& username, bool isOpti QNetworkAccessManager::GetOperation, callbackParams); } -QString extractUsernameFromPublicKeyRequest(QNetworkReply& requestReply) { +QString extractUsernameFromPublicKeyRequest(QNetworkReply* requestReply) { // extract the username from the request url QString username; const QString PUBLIC_KEY_URL_REGEX_STRING = "api\\/v1\\/users\\/([A-Za-z0-9_\\.]+)\\/public_key"; QRegExp usernameRegex(PUBLIC_KEY_URL_REGEX_STRING); - if (usernameRegex.indexIn(requestReply.url().toString()) != -1) { + if (usernameRegex.indexIn(requestReply->url().toString()) != -1) { username = usernameRegex.cap(1); } return username.toLower(); } -void DomainGatekeeper::publicKeyJSONCallback(QNetworkReply& requestReply) { - QJsonObject jsonObject = QJsonDocument::fromJson(requestReply.readAll()).object(); +void DomainGatekeeper::publicKeyJSONCallback(QNetworkReply* requestReply) { + QJsonObject jsonObject = QJsonDocument::fromJson(requestReply->readAll()).object(); QString username = extractUsernameFromPublicKeyRequest(requestReply); bool isOptimisticKey = _inFlightPublicKeyRequests.take(username); @@ -707,8 +706,8 @@ void DomainGatekeeper::publicKeyJSONCallback(QNetworkReply& requestReply) { } } -void DomainGatekeeper::publicKeyJSONErrorCallback(QNetworkReply& requestReply) { - qDebug() << "publicKey api call failed:" << requestReply.error(); +void DomainGatekeeper::publicKeyJSONErrorCallback(QNetworkReply* requestReply) { + qDebug() << "publicKey api call failed:" << requestReply->error(); QString username = extractUsernameFromPublicKeyRequest(requestReply); _inFlightPublicKeyRequests.remove(username); } @@ -893,9 +892,8 @@ void DomainGatekeeper::getGroupMemberships(const QString& username) { JSONCallbackParameters callbackParams; - callbackParams.jsonCallbackReceiver = this; + callbackParams.callbackReceiver = this; callbackParams.jsonCallbackMethod = "getIsGroupMemberJSONCallback"; - callbackParams.errorCallbackReceiver = this; callbackParams.errorCallbackMethod = "getIsGroupMemberErrorCallback"; const QString GET_IS_GROUP_MEMBER_PATH = "api/v1/groups/members/%2"; @@ -906,18 +904,18 @@ void DomainGatekeeper::getGroupMemberships(const QString& username) { } -QString extractUsernameFromGroupMembershipsReply(QNetworkReply& requestReply) { +QString extractUsernameFromGroupMembershipsReply(QNetworkReply* requestReply) { // extract the username from the request url QString username; const QString GROUP_MEMBERSHIPS_URL_REGEX_STRING = "api\\/v1\\/groups\\/members\\/([A-Za-z0-9_\\.]+)"; QRegExp usernameRegex(GROUP_MEMBERSHIPS_URL_REGEX_STRING); - if (usernameRegex.indexIn(requestReply.url().toString()) != -1) { + if (usernameRegex.indexIn(requestReply->url().toString()) != -1) { username = usernameRegex.cap(1); } return username.toLower(); } -void DomainGatekeeper::getIsGroupMemberJSONCallback(QNetworkReply& requestReply) { +void DomainGatekeeper::getIsGroupMemberJSONCallback(QNetworkReply* requestReply) { // { // "data":{ // "username":"sethalves", @@ -934,7 +932,7 @@ void DomainGatekeeper::getIsGroupMemberJSONCallback(QNetworkReply& requestReply) // "status":"success" // } - QJsonObject jsonObject = QJsonDocument::fromJson(requestReply.readAll()).object(); + QJsonObject jsonObject = QJsonDocument::fromJson(requestReply->readAll()).object(); if (jsonObject["status"].toString() == "success") { QJsonObject data = jsonObject["data"].toObject(); QJsonObject groups = data["groups"].toObject(); @@ -953,16 +951,15 @@ void DomainGatekeeper::getIsGroupMemberJSONCallback(QNetworkReply& requestReply) _inFlightGroupMembershipsRequests.remove(extractUsernameFromGroupMembershipsReply(requestReply)); } -void DomainGatekeeper::getIsGroupMemberErrorCallback(QNetworkReply& requestReply) { - qDebug() << "getIsGroupMember api call failed:" << requestReply.error(); +void DomainGatekeeper::getIsGroupMemberErrorCallback(QNetworkReply* requestReply) { + qDebug() << "getIsGroupMember api call failed:" << requestReply->error(); _inFlightGroupMembershipsRequests.remove(extractUsernameFromGroupMembershipsReply(requestReply)); } void DomainGatekeeper::getDomainOwnerFriendsList() { JSONCallbackParameters callbackParams; - callbackParams.jsonCallbackReceiver = this; + callbackParams.callbackReceiver = this; callbackParams.jsonCallbackMethod = "getDomainOwnerFriendsListJSONCallback"; - callbackParams.errorCallbackReceiver = this; callbackParams.errorCallbackMethod = "getDomainOwnerFriendsListErrorCallback"; const QString GET_FRIENDS_LIST_PATH = "api/v1/user/friends"; @@ -974,7 +971,7 @@ void DomainGatekeeper::getDomainOwnerFriendsList() { } -void DomainGatekeeper::getDomainOwnerFriendsListJSONCallback(QNetworkReply& requestReply) { +void DomainGatekeeper::getDomainOwnerFriendsListJSONCallback(QNetworkReply* requestReply) { // { // status: "success", // data: { @@ -991,7 +988,7 @@ void DomainGatekeeper::getDomainOwnerFriendsListJSONCallback(QNetworkReply& requ // ] // } // } - QJsonObject jsonObject = QJsonDocument::fromJson(requestReply.readAll()).object(); + QJsonObject jsonObject = QJsonDocument::fromJson(requestReply->readAll()).object(); if (jsonObject["status"].toString() == "success") { _domainOwnerFriends.clear(); QJsonArray friends = jsonObject["data"].toObject()["friends"].toArray(); @@ -1003,8 +1000,8 @@ void DomainGatekeeper::getDomainOwnerFriendsListJSONCallback(QNetworkReply& requ } } -void DomainGatekeeper::getDomainOwnerFriendsListErrorCallback(QNetworkReply& requestReply) { - qDebug() << "getDomainOwnerFriendsList api call failed:" << requestReply.error(); +void DomainGatekeeper::getDomainOwnerFriendsListErrorCallback(QNetworkReply* requestReply) { + qDebug() << "getDomainOwnerFriendsList api call failed:" << requestReply->error(); } void DomainGatekeeper::refreshGroupsCache() { diff --git a/domain-server/src/DomainGatekeeper.h b/domain-server/src/DomainGatekeeper.h index 2cb9b4c8a9..f8d79179d6 100644 --- a/domain-server/src/DomainGatekeeper.h +++ b/domain-server/src/DomainGatekeeper.h @@ -51,14 +51,14 @@ public slots: void processICEPingReplyPacket(QSharedPointer message); void processICEPeerInformationPacket(QSharedPointer message); - void publicKeyJSONCallback(QNetworkReply& requestReply); - void publicKeyJSONErrorCallback(QNetworkReply& requestReply); + void publicKeyJSONCallback(QNetworkReply* requestReply); + void publicKeyJSONErrorCallback(QNetworkReply* requestReply); - void getIsGroupMemberJSONCallback(QNetworkReply& requestReply); - void getIsGroupMemberErrorCallback(QNetworkReply& requestReply); + void getIsGroupMemberJSONCallback(QNetworkReply* requestReply); + void getIsGroupMemberErrorCallback(QNetworkReply* requestReply); - void getDomainOwnerFriendsListJSONCallback(QNetworkReply& requestReply); - void getDomainOwnerFriendsListErrorCallback(QNetworkReply& requestReply); + void getDomainOwnerFriendsListJSONCallback(QNetworkReply* requestReply); + void getDomainOwnerFriendsListErrorCallback(QNetworkReply* requestReply); void refreshGroupsCache(); diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index a34deebc95..eccd1c1e20 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -514,13 +514,13 @@ void DomainServer::getTemporaryName(bool force) { // request a temporary name from the metaverse auto accountManager = DependencyManager::get(); - JSONCallbackParameters callbackParameters { this, "handleTempDomainSuccess", this, "handleTempDomainError" }; + JSONCallbackParameters callbackParameters { this, "handleTempDomainSuccess", "handleTempDomainError" }; accountManager->sendRequest("/api/v1/domains/temporary", AccountManagerAuth::None, QNetworkAccessManager::PostOperation, callbackParameters); } -void DomainServer::handleTempDomainSuccess(QNetworkReply& requestReply) { - QJsonObject jsonObject = QJsonDocument::fromJson(requestReply.readAll()).object(); +void DomainServer::handleTempDomainSuccess(QNetworkReply* requestReply) { + QJsonObject jsonObject = QJsonDocument::fromJson(requestReply->readAll()).object(); // grab the information for the new domain static const QString DATA_KEY = "data"; @@ -565,7 +565,7 @@ void DomainServer::handleTempDomainSuccess(QNetworkReply& requestReply) { } } -void DomainServer::handleTempDomainError(QNetworkReply& requestReply) { +void DomainServer::handleTempDomainError(QNetworkReply* requestReply) { qWarning() << "A temporary name was requested but there was an error creating one. Please try again via domain-server relaunch" << "or from the domain-server settings."; } @@ -1345,7 +1345,7 @@ void DomainServer::sendPendingTransactionsToServer() { JSONCallbackParameters transactionCallbackParams; - transactionCallbackParams.jsonCallbackReceiver = this; + transactionCallbackParams.callbackReceiver = this; transactionCallbackParams.jsonCallbackMethod = "transactionJSONCallback"; while (i != _pendingAssignmentCredits.end()) { @@ -1449,11 +1449,11 @@ void DomainServer::sendHeartbeatToMetaverse(const QString& networkAddress) { DependencyManager::get()->sendRequest(DOMAIN_UPDATE.arg(uuidStringWithoutCurlyBraces(getID())), AccountManagerAuth::Optional, QNetworkAccessManager::PutOperation, - JSONCallbackParameters(nullptr, QString(), this, "handleMetaverseHeartbeatError"), + JSONCallbackParameters(this, QString(), "handleMetaverseHeartbeatError"), domainUpdateJSON.toUtf8()); } -void DomainServer::handleMetaverseHeartbeatError(QNetworkReply& requestReply) { +void DomainServer::handleMetaverseHeartbeatError(QNetworkReply* requestReply) { if (!_metaverseHeartbeatTimer) { // avoid rehandling errors from the same issue return; @@ -1462,13 +1462,13 @@ void DomainServer::handleMetaverseHeartbeatError(QNetworkReply& requestReply) { // only attempt to grab a new temporary name if we're already a temporary domain server if (_type == MetaverseTemporaryDomain) { // check if we need to force a new temporary domain name - switch (requestReply.error()) { + switch (requestReply->error()) { // if we have a temporary domain with a bad token, we get a 401 case QNetworkReply::NetworkError::AuthenticationRequiredError: { static const QString DATA_KEY = "data"; static const QString TOKEN_KEY = "api_key"; - QJsonObject jsonObject = QJsonDocument::fromJson(requestReply.readAll()).object(); + QJsonObject jsonObject = QJsonDocument::fromJson(requestReply->readAll()).object(); auto tokenFailure = jsonObject[DATA_KEY].toObject()[TOKEN_KEY]; if (!tokenFailure.isNull()) { @@ -1531,9 +1531,8 @@ void DomainServer::sendICEServerAddressToMetaverseAPI() { // make sure we hear about failure so we can retry JSONCallbackParameters callbackParameters; - callbackParameters.errorCallbackReceiver = this; + callbackParameters.callbackReceiver = this; callbackParameters.errorCallbackMethod = "handleFailedICEServerAddressUpdate"; - callbackParameters.jsonCallbackReceiver = this; callbackParameters.jsonCallbackMethod = "handleSuccessfulICEServerAddressUpdate"; static bool printedIceServerMessage = false; @@ -1552,7 +1551,7 @@ void DomainServer::sendICEServerAddressToMetaverseAPI() { domainUpdateJSON.toUtf8()); } -void DomainServer::handleSuccessfulICEServerAddressUpdate(QNetworkReply& requestReply) { +void DomainServer::handleSuccessfulICEServerAddressUpdate(QNetworkReply* requestReply) { _sendICEServerAddressToMetaverseAPIInProgress = false; if (_sendICEServerAddressToMetaverseAPIRedo) { qDebug() << "ice-server address updated with metaverse, but has since changed. redoing update..."; @@ -1563,7 +1562,7 @@ void DomainServer::handleSuccessfulICEServerAddressUpdate(QNetworkReply& request } } -void DomainServer::handleFailedICEServerAddressUpdate(QNetworkReply& requestReply) { +void DomainServer::handleFailedICEServerAddressUpdate(QNetworkReply* requestReply) { _sendICEServerAddressToMetaverseAPIInProgress = false; if (_sendICEServerAddressToMetaverseAPIRedo) { // if we have new data, retry right away, even though the previous attempt didn't go well. @@ -1573,7 +1572,7 @@ void DomainServer::handleFailedICEServerAddressUpdate(QNetworkReply& requestRepl const int ICE_SERVER_UPDATE_RETRY_MS = 2 * 1000; qWarning() << "Failed to update ice-server address with High Fidelity Metaverse - error was" - << requestReply.errorString(); + << requestReply->errorString(); qWarning() << "\tRe-attempting in" << ICE_SERVER_UPDATE_RETRY_MS / 1000 << "seconds"; QTimer::singleShot(ICE_SERVER_UPDATE_RETRY_MS, this, SLOT(sendICEServerAddressToMetaverseAPI())); diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 3703877fa1..c69267f379 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -108,10 +108,10 @@ private slots: void sendHeartbeatToIceServer(); void handleConnectedNode(SharedNodePointer newNode); - void handleTempDomainSuccess(QNetworkReply& requestReply); - void handleTempDomainError(QNetworkReply& requestReply); + void handleTempDomainSuccess(QNetworkReply* requestReply); + void handleTempDomainError(QNetworkReply* requestReply); - void handleMetaverseHeartbeatError(QNetworkReply& requestReply); + void handleMetaverseHeartbeatError(QNetworkReply* requestReply); void queuedQuit(QString quitMessage, int exitCode); @@ -121,8 +121,8 @@ private slots: void handleICEHostInfo(const QHostInfo& hostInfo); void sendICEServerAddressToMetaverseAPI(); - void handleSuccessfulICEServerAddressUpdate(QNetworkReply& requestReply); - void handleFailedICEServerAddressUpdate(QNetworkReply& requestReply); + void handleSuccessfulICEServerAddressUpdate(QNetworkReply* requestReply); + void handleFailedICEServerAddressUpdate(QNetworkReply* requestReply); void updateReplicatedNodes(); void updateDownstreamNodes(); diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index c46b2eda49..2bcaa8899e 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -1815,9 +1815,8 @@ void DomainServerSettingsManager::apiRefreshGroupInformation() { void DomainServerSettingsManager::apiGetGroupID(const QString& groupName) { JSONCallbackParameters callbackParams; - callbackParams.jsonCallbackReceiver = this; + callbackParams.callbackReceiver = this; callbackParams.jsonCallbackMethod = "apiGetGroupIDJSONCallback"; - callbackParams.errorCallbackReceiver = this; callbackParams.errorCallbackMethod = "apiGetGroupIDErrorCallback"; const QString GET_GROUP_ID_PATH = "api/v1/groups/names/%1"; @@ -1826,7 +1825,7 @@ void DomainServerSettingsManager::apiGetGroupID(const QString& groupName) { QNetworkAccessManager::GetOperation, callbackParams); } -void DomainServerSettingsManager::apiGetGroupIDJSONCallback(QNetworkReply& requestReply) { +void DomainServerSettingsManager::apiGetGroupIDJSONCallback(QNetworkReply* requestReply) { // { // "data":{ // "groups":[{ @@ -1857,7 +1856,7 @@ void DomainServerSettingsManager::apiGetGroupIDJSONCallback(QNetworkReply& reque // }, // "status":"success" // } - QJsonObject jsonObject = QJsonDocument::fromJson(requestReply.readAll()).object(); + QJsonObject jsonObject = QJsonDocument::fromJson(requestReply->readAll()).object(); if (jsonObject["status"].toString() == "success") { QJsonArray groups = jsonObject["data"].toObject()["groups"].toArray(); for (int i = 0; i < groups.size(); i++) { @@ -1876,15 +1875,14 @@ void DomainServerSettingsManager::apiGetGroupIDJSONCallback(QNetworkReply& reque } } -void DomainServerSettingsManager::apiGetGroupIDErrorCallback(QNetworkReply& requestReply) { - qDebug() << "******************** getGroupID api call failed:" << requestReply.error(); +void DomainServerSettingsManager::apiGetGroupIDErrorCallback(QNetworkReply* requestReply) { + qDebug() << "******************** getGroupID api call failed:" << requestReply->error(); } void DomainServerSettingsManager::apiGetGroupRanks(const QUuid& groupID) { JSONCallbackParameters callbackParams; - callbackParams.jsonCallbackReceiver = this; + callbackParams.callbackReceiver = this; callbackParams.jsonCallbackMethod = "apiGetGroupRanksJSONCallback"; - callbackParams.errorCallbackReceiver = this; callbackParams.errorCallbackMethod = "apiGetGroupRanksErrorCallback"; const QString GET_GROUP_RANKS_PATH = "api/v1/groups/%1/ranks"; @@ -1893,7 +1891,7 @@ void DomainServerSettingsManager::apiGetGroupRanks(const QUuid& groupID) { QNetworkAccessManager::GetOperation, callbackParams); } -void DomainServerSettingsManager::apiGetGroupRanksJSONCallback(QNetworkReply& requestReply) { +void DomainServerSettingsManager::apiGetGroupRanksJSONCallback(QNetworkReply* requestReply) { // { // "data":{ // "groups":{ @@ -1926,7 +1924,7 @@ void DomainServerSettingsManager::apiGetGroupRanksJSONCallback(QNetworkReply& re // } bool changed = false; - QJsonObject jsonObject = QJsonDocument::fromJson(requestReply.readAll()).object(); + QJsonObject jsonObject = QJsonDocument::fromJson(requestReply->readAll()).object(); if (jsonObject["status"].toString() == "success") { QJsonObject groups = jsonObject["data"].toObject()["groups"].toObject(); @@ -1972,8 +1970,8 @@ void DomainServerSettingsManager::apiGetGroupRanksJSONCallback(QNetworkReply& re } } -void DomainServerSettingsManager::apiGetGroupRanksErrorCallback(QNetworkReply& requestReply) { - qDebug() << "******************** getGroupRanks api call failed:" << requestReply.error(); +void DomainServerSettingsManager::apiGetGroupRanksErrorCallback(QNetworkReply* requestReply) { + qDebug() << "******************** getGroupRanks api call failed:" << requestReply->error(); } void DomainServerSettingsManager::recordGroupMembership(const QString& name, const QUuid groupID, QUuid rankID) { diff --git a/domain-server/src/DomainServerSettingsManager.h b/domain-server/src/DomainServerSettingsManager.h index 252ff79ae2..bcd33c2bb0 100644 --- a/domain-server/src/DomainServerSettingsManager.h +++ b/domain-server/src/DomainServerSettingsManager.h @@ -133,10 +133,10 @@ signals: void settingsUpdated(); public slots: - void apiGetGroupIDJSONCallback(QNetworkReply& requestReply); - void apiGetGroupIDErrorCallback(QNetworkReply& requestReply); - void apiGetGroupRanksJSONCallback(QNetworkReply& requestReply); - void apiGetGroupRanksErrorCallback(QNetworkReply& requestReply); + void apiGetGroupIDJSONCallback(QNetworkReply* requestReply); + void apiGetGroupIDErrorCallback(QNetworkReply* requestReply); + void apiGetGroupRanksJSONCallback(QNetworkReply* requestReply); + void apiGetGroupRanksErrorCallback(QNetworkReply* requestReply); private slots: void processSettingsRequestPacket(QSharedPointer message); diff --git a/interface/resources/qml/hifi/audio/Audio.qml b/interface/resources/qml/hifi/audio/Audio.qml index ba50b7f238..cc1ba49984 100644 --- a/interface/resources/qml/hifi/audio/Audio.qml +++ b/interface/resources/qml/hifi/audio/Audio.qml @@ -129,12 +129,10 @@ Rectangle { id: stereoMic spacing: muteMic.spacing; text: qsTr("Enable stereo input"); - checked: AudioScriptingInterface.isStereoInput(); + checked: AudioScriptingInterface.isStereoInput; onClicked: { - var success = AudioScriptingInterface.setStereoInput(checked); - if (!success) { - checked = !checked; - } + AudioScriptingInterface.isStereoInput = checked; + checked = Qt.binding(function() { return AudioScriptingInterface.isStereoInput; }); // restore binding } } } diff --git a/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml b/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml index cb4913f999..861de001d8 100644 --- a/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml +++ b/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml @@ -17,7 +17,7 @@ PreferencesDialog { id: root objectName: "GeneralPreferencesDialog" title: "General Settings" - showCategories: ["User Interface", "HMD", "Snapshots", "Privacy"] + showCategories: ["User Interface", "Mouse Sensitivity", "HMD", "Snapshots", "Privacy"] property var settings: Settings { category: root.objectName property alias x: root.x diff --git a/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml b/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml index 63801019b9..4f1100f20b 100644 --- a/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml +++ b/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml @@ -32,6 +32,6 @@ StackView { TabletPreferencesDialog { id: root objectName: "TabletGeneralPreferences" - showCategories: ["User Interface", "HMD", "Snapshots", "Privacy"] + showCategories: ["User Interface", "Mouse Sensitivity", "HMD", "Snapshots", "Privacy"] } } diff --git a/interface/src/AndroidHelper.cpp b/interface/src/AndroidHelper.cpp index ef7319e63f..be41d434df 100644 --- a/interface/src/AndroidHelper.cpp +++ b/interface/src/AndroidHelper.cpp @@ -10,31 +10,11 @@ // #include "AndroidHelper.h" #include -#include AndroidHelper::AndroidHelper() { } AndroidHelper::~AndroidHelper() { - workerThread.quit(); - workerThread.wait(); -} - -void AndroidHelper::init() { - workerThread.start(); - _accountManager = QSharedPointer(new AccountManager, &QObject::deleteLater); - _accountManager->setIsAgent(true); - _accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL()); - _accountManager->setSessionID(DependencyManager::get()->getSessionID()); - connect(_accountManager.data(), &AccountManager::loginComplete, [](const QUrl& authURL) { - DependencyManager::get()->setAccountInfo(AndroidHelper::instance().getAccountManager()->getAccountInfo()); - DependencyManager::get()->setAuthURL(authURL); - }); - - connect(_accountManager.data(), &AccountManager::logoutComplete, [] () { - DependencyManager::get()->logout(); - }); - _accountManager->moveToThread(&workerThread); } void AndroidHelper::requestActivity(const QString &activityName, const bool backToScene) { diff --git a/interface/src/AndroidHelper.h b/interface/src/AndroidHelper.h index 007c0db4a5..cecae4a79e 100644 --- a/interface/src/AndroidHelper.h +++ b/interface/src/AndroidHelper.h @@ -13,8 +13,6 @@ #define hifi_Android_Helper_h #include -#include -#include class AndroidHelper : public QObject { Q_OBJECT @@ -23,7 +21,6 @@ public: static AndroidHelper instance; return instance; } - void init(); void requestActivity(const QString &activityName, const bool backToScene); void notifyLoadComplete(); void notifyEnterForeground(); @@ -31,7 +28,6 @@ public: void performHapticFeedback(int duration); - QSharedPointer getAccountManager() { return _accountManager; } AndroidHelper(AndroidHelper const&) = delete; void operator=(AndroidHelper const&) = delete; @@ -49,8 +45,6 @@ signals: private: AndroidHelper(); ~AndroidHelper(); - QSharedPointer _accountManager; - QThread workerThread; }; #endif diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6f95a1afe8..a60d72073c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1081,6 +1081,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo auto nodeList = DependencyManager::get(); nodeList->startThread(); + // move the AddressManager to the NodeList thread so that domain resets due to domain changes always occur + // before we tell MyAvatar to go to a new location in the new domain + auto addressManager = DependencyManager::get(); + addressManager->moveToThread(nodeList->thread()); + const char** constArgv = const_cast(argv); if (cmdOptionExists(argc, constArgv, "--disableWatchdog")) { DISABLE_WATCHDOG = true; @@ -1231,8 +1236,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo accountManager->setIsAgent(true); accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL()); - auto addressManager = DependencyManager::get(); - // use our MyAvatar position and quat for address manager path addressManager->setPositionGetter([this]{ return getMyAvatar()->getWorldPosition(); }); addressManager->setOrientationGetter([this]{ return getMyAvatar()->getWorldOrientation(); }); @@ -2256,7 +2259,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo qCDebug(interfaceapp) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(accountManager->getSessionID()); #if defined(Q_OS_ANDROID) - AndroidHelper::instance().init(); connect(&AndroidHelper::instance(), &AndroidHelper::enterBackground, this, &Application::enterBackground); connect(&AndroidHelper::instance(), &AndroidHelper::enterForeground, this, &Application::enterForeground); AndroidHelper::instance().notifyLoadComplete(); diff --git a/interface/src/DiscoverabilityManager.cpp b/interface/src/DiscoverabilityManager.cpp index d39aaa4f1a..e3a99475ef 100644 --- a/interface/src/DiscoverabilityManager.cpp +++ b/interface/src/DiscoverabilityManager.cpp @@ -97,7 +97,7 @@ void DiscoverabilityManager::updateLocation() { locationObject.insert(AVAILABILITY_KEY_IN_LOCATION, findableByString(static_cast(_mode.get()))); JSONCallbackParameters callbackParameters; - callbackParameters.jsonCallbackReceiver = this; + callbackParameters.callbackReceiver = this; callbackParameters.jsonCallbackMethod = "handleHeartbeatResponse"; // figure out if we'll send a fresh location or just a simple heartbeat @@ -121,7 +121,7 @@ void DiscoverabilityManager::updateLocation() { // we still send a heartbeat to the metaverse server for stats collection JSONCallbackParameters callbackParameters; - callbackParameters.jsonCallbackReceiver = this; + callbackParameters.callbackReceiver = this; callbackParameters.jsonCallbackMethod = "handleHeartbeatResponse"; accountManager->sendRequest(API_USER_HEARTBEAT_PATH, AccountManagerAuth::Optional, @@ -136,7 +136,7 @@ void DiscoverabilityManager::updateLocation() { setCrashAnnotation("address", currentAddress.toString().toStdString()); } -void DiscoverabilityManager::handleHeartbeatResponse(QNetworkReply& requestReply) { +void DiscoverabilityManager::handleHeartbeatResponse(QNetworkReply* requestReply) { auto dataObject = AccountManager::dataObjectFromResponse(requestReply); if (!dataObject.isEmpty()) { diff --git a/interface/src/DiscoverabilityManager.h b/interface/src/DiscoverabilityManager.h index 0c62ad5663..fc0b1fa759 100644 --- a/interface/src/DiscoverabilityManager.h +++ b/interface/src/DiscoverabilityManager.h @@ -51,7 +51,7 @@ public: static QString findableByString(Discoverability::Mode discoverabilityMode); private slots: - void handleHeartbeatResponse(QNetworkReply& requestReply); + void handleHeartbeatResponse(QNetworkReply* requestReply); private: DiscoverabilityManager(); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index a102f2a42e..fcf7b53536 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -283,7 +283,7 @@ Menu::Menu() { MenuWrapper* settingsMenu = addMenu("Settings"); // Settings > General... - action = addActionToQMenuAndActionHash(settingsMenu, MenuOption::Preferences, Qt::CTRL | Qt::Key_G, nullptr, nullptr, QAction::PreferencesRole); + action = addActionToQMenuAndActionHash(settingsMenu, MenuOption::Preferences, Qt::CTRL | Qt::Key_G, nullptr, nullptr); connect(action, &QAction::triggered, [] { qApp->showDialog(QString("hifi/dialogs/GeneralPreferencesDialog.qml"), QString("hifi/tablet/TabletGeneralPreferences.qml"), "GeneralPreferencesDialog"); diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index c63095a204..8a25c21946 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -36,13 +36,13 @@ #include #include #include -#include #include #include "Application.h" #include "InterfaceLogging.h" #include "Menu.h" #include "MyAvatar.h" +#include "OtherAvatar.h" #include "SceneScriptingInterface.h" // 50 times per second - target is 45hz, but this helps account for any small deviations @@ -192,6 +192,15 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { while (!sortedAvatars.empty()) { const SortableAvatar& sortData = sortedAvatars.top(); const auto avatar = std::static_pointer_cast(sortData.getAvatar()); + const auto otherAvatar = std::static_pointer_cast(sortData.getAvatar()); + + // if the geometry is loaded then turn off the orb + if (avatar->getSkeletonModel()->isLoaded()) { + // remove the orb if it is there + otherAvatar->removeOrb(); + } else { + otherAvatar->updateOrbPosition(); + } bool ignoring = DependencyManager::get()->isPersonalMutingNode(avatar->getID()); if (ignoring) { diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index b0369303e9..ed7ce87db2 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -532,10 +532,14 @@ void MyAvatar::forgetChild(SpatiallyNestablePointer newChild) const { SpatiallyNestable::forgetChild(newChild); } -void MyAvatar::updateChildCauterization(SpatiallyNestablePointer object) { +void MyAvatar::recalculateChildCauterization() const { + _cauterizationNeedsUpdate = true; +} + +void MyAvatar::updateChildCauterization(SpatiallyNestablePointer object, bool cauterize) { if (object->getNestableType() == NestableType::Entity) { EntityItemPointer entity = std::static_pointer_cast(object); - entity->setCauterized(!_prevShouldDrawHead); + entity->setCauterized(cauterize); } } @@ -545,17 +549,42 @@ void MyAvatar::simulate(float deltaTime) { animateScaleChanges(deltaTime); if (_cauterizationNeedsUpdate) { - const std::unordered_set& headBoneSet = _skeletonModel->getCauterizeBoneSet(); + _cauterizationNeedsUpdate = false; + + // Redisplay cauterized entities that are no longer children of the avatar. + auto cauterizedChild = _cauterizedChildrenOfHead.begin(); + if (cauterizedChild != _cauterizedChildrenOfHead.end()) { + auto children = getChildren(); + while (cauterizedChild != _cauterizedChildrenOfHead.end()) { + if (!children.contains(*cauterizedChild)) { + updateChildCauterization(*cauterizedChild, false); + cauterizedChild = _cauterizedChildrenOfHead.erase(cauterizedChild); + } else { + ++cauterizedChild; + } + } + } + + // Update cauterization of entities that are children of the avatar. + auto headBoneSet = _skeletonModel->getCauterizeBoneSet(); forEachChild([&](SpatiallyNestablePointer object) { bool isChildOfHead = headBoneSet.find(object->getParentJointIndex()) != headBoneSet.end(); if (isChildOfHead) { - updateChildCauterization(object); + // Cauterize or display children of head per head drawing state. + updateChildCauterization(object, !_prevShouldDrawHead); object->forEachDescendant([&](SpatiallyNestablePointer descendant) { - updateChildCauterization(descendant); + updateChildCauterization(descendant, !_prevShouldDrawHead); }); + _cauterizedChildrenOfHead.insert(object); + } else if (_cauterizedChildrenOfHead.find(object) != _cauterizedChildrenOfHead.end()) { + // Redisplay cauterized children that are not longer children of the head. + updateChildCauterization(object, false); + object->forEachDescendant([&](SpatiallyNestablePointer descendant) { + updateChildCauterization(descendant, false); + }); + _cauterizedChildrenOfHead.erase(object); } }); - _cauterizationNeedsUpdate = false; } { @@ -685,7 +714,8 @@ void MyAvatar::simulate(float deltaTime) { entityTree->recurseTreeWithOperator(&moveOperator); } }); - _characterController.setFlyingAllowed(zoneAllowsFlying && _enableFlying); + bool isPhysicsEnabled = qApp->isPhysicsEnabled(); + _characterController.setFlyingAllowed(zoneAllowsFlying && (_enableFlying || !isPhysicsEnabled)); _characterController.setCollisionlessAllowed(collisionlessAllowed); } @@ -1068,8 +1098,8 @@ void MyAvatar::saveData() { settings.setValue("displayName", _displayName); settings.setValue("collisionSoundURL", _collisionSoundURL); settings.setValue("useSnapTurn", _useSnapTurn); - settings.setValue("clearOverlayWhenMoving", _clearOverlayWhenMoving); settings.setValue("userHeight", getUserHeight()); + settings.setValue("enabledFlying", getFlyingEnabled()); settings.endGroup(); } @@ -1219,11 +1249,10 @@ void MyAvatar::loadData() { settings.remove("avatarEntityData"); } setAvatarEntityDataChanged(true); - + setFlyingEnabled(settings.value("enabledFlying").toBool()); setDisplayName(settings.value("displayName").toString()); setCollisionSoundURL(settings.value("collisionSoundURL", DEFAULT_AVATAR_COLLISION_SOUND_URL).toString()); setSnapTurn(settings.value("useSnapTurn", _useSnapTurn).toBool()); - setClearOverlayWhenMoving(settings.value("clearOverlayWhenMoving", _clearOverlayWhenMoving).toBool()); setDominantHand(settings.value("dominantHand", _dominantHand).toString().toLower()); setUserHeight(settings.value("userHeight", DEFAULT_AVATAR_HEIGHT).toDouble()); settings.endGroup(); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 1a6feb142a..a3b07d400f 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -250,7 +250,7 @@ public: Q_ENUM(DriveKeys) explicit MyAvatar(QThread* thread); - ~MyAvatar(); + virtual ~MyAvatar(); void instantiableAvatar() override {}; void registerMetaTypes(ScriptEnginePointer engine); @@ -469,16 +469,6 @@ public: * @param {boolean} on */ Q_INVOKABLE void setSnapTurn(bool on) { _useSnapTurn = on; } - /**jsdoc - * @function MyAvatar.getClearOverlayWhenMoving - * @returns {boolean} - */ - Q_INVOKABLE bool getClearOverlayWhenMoving() const { return _clearOverlayWhenMoving; } - /**jsdoc - * @function MyAvatar.setClearOverlayWhenMoving - * @param {boolean} on - */ - Q_INVOKABLE void setClearOverlayWhenMoving(bool on) { _clearOverlayWhenMoving = on; } /**jsdoc @@ -1374,6 +1364,7 @@ private slots: protected: virtual void beParentOfChild(SpatiallyNestablePointer newChild) const override; virtual void forgetChild(SpatiallyNestablePointer newChild) const override; + virtual void recalculateChildCauterization() const override; private: @@ -1433,7 +1424,7 @@ private: std::array _driveKeys; std::bitset _disabledDriveKeys; - bool _enableFlying { true }; + bool _enableFlying { false }; bool _wasPushing { false }; bool _isPushing { false }; bool _isBeingPushed { false }; @@ -1495,7 +1486,6 @@ private: ThreadSafeValueCache _prefOverrideAnimGraphUrl; QUrl _fstAnimGraphOverrideUrl; bool _useSnapTurn { true }; - bool _clearOverlayWhenMoving { true }; QString _dominantHand { DOMINANT_RIGHT_HAND }; const float ROLL_CONTROL_DEAD_ZONE_DEFAULT = 8.0f; // degrees @@ -1566,6 +1556,7 @@ private: glm::quat _goToOrientation; std::unordered_set _headBoneSet; + std::unordered_set _cauterizedChildrenOfHead; bool _prevShouldDrawHead; bool _rigEnabled { true }; @@ -1621,7 +1612,7 @@ private: // height of user in sensor space, when standing erect. ThreadSafeValueCache _userHeight { DEFAULT_AVATAR_HEIGHT }; - void updateChildCauterization(SpatiallyNestablePointer object); + void updateChildCauterization(SpatiallyNestablePointer object, bool cauterize); // max unscaled forward movement speed ThreadSafeValueCache _walkSpeed { DEFAULT_AVATAR_MAX_WALKING_SPEED }; diff --git a/interface/src/avatar/OtherAvatar.cpp b/interface/src/avatar/OtherAvatar.cpp new file mode 100644 index 0000000000..5e51658128 --- /dev/null +++ b/interface/src/avatar/OtherAvatar.cpp @@ -0,0 +1,60 @@ +// +// Created by Bradley Austin Davis on 2017/04/27 +// Copyright 2013-2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "OtherAvatar.h" +#include "Application.h" + +OtherAvatar::OtherAvatar(QThread* thread) : Avatar(thread) { + // give the pointer to our head to inherited _headData variable from AvatarData + _headData = new Head(this); + _skeletonModel = std::make_shared(this, nullptr); + _skeletonModel->setLoadingPriority(OTHERAVATAR_LOADING_PRIORITY); + connect(_skeletonModel.get(), &Model::setURLFinished, this, &Avatar::setModelURLFinished); + connect(_skeletonModel.get(), &Model::rigReady, this, &Avatar::rigReady); + connect(_skeletonModel.get(), &Model::rigReset, this, &Avatar::rigReset); + + // add the purple orb + createOrb(); +} + +OtherAvatar::~OtherAvatar() { + removeOrb(); +} + +void OtherAvatar::removeOrb() { + if (qApp->getOverlays().isAddedOverlay(_otherAvatarOrbMeshPlaceholderID)) { + qApp->getOverlays().deleteOverlay(_otherAvatarOrbMeshPlaceholderID); + } +} + +void OtherAvatar::updateOrbPosition() { + if (_otherAvatarOrbMeshPlaceholder != nullptr) { + _otherAvatarOrbMeshPlaceholder->setWorldPosition(getHead()->getPosition()); + } +} + +void OtherAvatar::createOrb() { + if (_otherAvatarOrbMeshPlaceholderID == UNKNOWN_OVERLAY_ID || + !qApp->getOverlays().isAddedOverlay(_otherAvatarOrbMeshPlaceholderID)) { + _otherAvatarOrbMeshPlaceholder = std::make_shared(); + _otherAvatarOrbMeshPlaceholder->setAlpha(1.0f); + _otherAvatarOrbMeshPlaceholder->setColor({ 0xFF, 0x00, 0xFF }); + _otherAvatarOrbMeshPlaceholder->setIsSolid(false); + _otherAvatarOrbMeshPlaceholder->setPulseMin(0.5); + _otherAvatarOrbMeshPlaceholder->setPulseMax(1.0); + _otherAvatarOrbMeshPlaceholder->setColorPulse(1.0); + _otherAvatarOrbMeshPlaceholder->setIgnoreRayIntersection(true); + _otherAvatarOrbMeshPlaceholder->setDrawInFront(false); + _otherAvatarOrbMeshPlaceholderID = qApp->getOverlays().addOverlay(_otherAvatarOrbMeshPlaceholder); + // Position focus + _otherAvatarOrbMeshPlaceholder->setWorldOrientation(glm::quat(0.0f, 0.0f, 0.0f, 1.0)); + _otherAvatarOrbMeshPlaceholder->setWorldPosition(getHead()->getPosition()); + _otherAvatarOrbMeshPlaceholder->setDimensions(glm::vec3(0.5f, 0.5f, 0.5f)); + _otherAvatarOrbMeshPlaceholder->setVisible(true); + } +} diff --git a/interface/src/avatar/OtherAvatar.h b/interface/src/avatar/OtherAvatar.h new file mode 100644 index 0000000000..f33952b78b --- /dev/null +++ b/interface/src/avatar/OtherAvatar.h @@ -0,0 +1,32 @@ +// +// Created by Bradley Austin Davis on 2017/04/27 +// Copyright 2013-2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_OtherAvatar_h +#define hifi_OtherAvatar_h + +#include +#include "ui/overlays/Overlays.h" +#include "ui/overlays/Sphere3DOverlay.h" +#include "InterfaceLogging.h" + +class OtherAvatar : public Avatar { +public: + explicit OtherAvatar(QThread* thread); + virtual ~OtherAvatar(); + + virtual void instantiableAvatar() override { }; + virtual void createOrb() override; + void updateOrbPosition(); + void removeOrb(); + +protected: + std::shared_ptr _otherAvatarOrbMeshPlaceholder { nullptr }; + OverlayID _otherAvatarOrbMeshPlaceholderID { UNKNOWN_OVERLAY_ID }; +}; + +#endif // hifi_OtherAvatar_h diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index 69698e82a6..702251f867 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -28,15 +28,15 @@ // account synthesizes a result {status: 'success', data: {keyStatus: "preexisting"|"conflicting"|"ok"}} -QJsonObject Ledger::apiResponse(const QString& label, QNetworkReply& reply) { - QByteArray response = reply.readAll(); +QJsonObject Ledger::apiResponse(const QString& label, QNetworkReply* reply) { + QByteArray response = reply->readAll(); QJsonObject data = QJsonDocument::fromJson(response).object(); qInfo(commerce) << label << "response" << QJsonDocument(data).toJson(QJsonDocument::Compact); return data; } // Non-200 responses are not json: -QJsonObject Ledger::failResponse(const QString& label, QNetworkReply& reply) { - QString response = reply.readAll(); +QJsonObject Ledger::failResponse(const QString& label, QNetworkReply* reply) { + QString response = reply->readAll(); qWarning(commerce) << "FAILED" << label << response; // tempResult will be NULL if the response isn't valid JSON. @@ -52,8 +52,8 @@ QJsonObject Ledger::failResponse(const QString& label, QNetworkReply& reply) { return tempResult.object(); } } -#define ApiHandler(NAME) void Ledger::NAME##Success(QNetworkReply& reply) { emit NAME##Result(apiResponse(#NAME, reply)); } -#define FailHandler(NAME) void Ledger::NAME##Failure(QNetworkReply& reply) { emit NAME##Result(failResponse(#NAME, reply)); } +#define ApiHandler(NAME) void Ledger::NAME##Success(QNetworkReply* reply) { emit NAME##Result(apiResponse(#NAME, reply)); } +#define FailHandler(NAME) void Ledger::NAME##Failure(QNetworkReply* reply) { emit NAME##Result(failResponse(#NAME, reply)); } #define Handler(NAME) ApiHandler(NAME) FailHandler(NAME) Handler(buy) Handler(receiveAt) @@ -68,7 +68,7 @@ Handler(updateItem) void Ledger::send(const QString& endpoint, const QString& success, const QString& fail, QNetworkAccessManager::Operation method, AccountManagerAuth::Type authType, QJsonObject request) { auto accountManager = DependencyManager::get(); const QString URL = "/api/v1/commerce/"; - JSONCallbackParameters callbackParams(this, success, this, fail); + JSONCallbackParameters callbackParams(this, success, fail); qCInfo(commerce) << "Sending" << endpoint << QJsonDocument(request).toJson(QJsonDocument::Compact); accountManager->sendRequest(URL + endpoint, authType, @@ -223,12 +223,12 @@ QString transactionString(const QJsonObject& valueObject) { } static const QString MARKETPLACE_ITEMS_BASE_URL = NetworkingConstants::METAVERSE_SERVER_URL().toString() + "/marketplace/items/"; -void Ledger::historySuccess(QNetworkReply& reply) { +void Ledger::historySuccess(QNetworkReply* reply) { // here we send a historyResult with some extra stuff in it // Namely, the styled text we'd like to show. The issue is the // QML cannot do that easily since it doesn't know what the wallet // public key(s) are. Let's keep it that way - QByteArray response = reply.readAll(); + QByteArray response = reply->readAll(); QJsonObject data = QJsonDocument::fromJson(response).object(); qInfo(commerce) << "history" << "response" << QJsonDocument(data).toJson(QJsonDocument::Compact); @@ -262,7 +262,7 @@ void Ledger::historySuccess(QNetworkReply& reply) { emit historyResult(newData); } -void Ledger::historyFailure(QNetworkReply& reply) { +void Ledger::historyFailure(QNetworkReply* reply) { failResponse("history", reply); } @@ -273,10 +273,10 @@ void Ledger::history(const QStringList& keys, const int& pageNumber, const int& keysQuery("history", "historySuccess", "historyFailure", params); } -void Ledger::accountSuccess(QNetworkReply& reply) { +void Ledger::accountSuccess(QNetworkReply* reply) { // lets set the appropriate stuff in the wallet now auto wallet = DependencyManager::get(); - QByteArray response = reply.readAll(); + QByteArray response = reply->readAll(); QJsonObject data = QJsonDocument::fromJson(response).object()["data"].toObject(); auto salt = QByteArray::fromBase64(data["salt"].toString().toUtf8()); @@ -312,7 +312,7 @@ void Ledger::accountSuccess(QNetworkReply& reply) { emit accountResult(responseData); } -void Ledger::accountFailure(QNetworkReply& reply) { +void Ledger::accountFailure(QNetworkReply* reply) { failResponse("account", reply); } void Ledger::account() { @@ -320,8 +320,8 @@ void Ledger::account() { } // The api/failResponse is called just for the side effect of logging. -void Ledger::updateLocationSuccess(QNetworkReply& reply) { apiResponse("updateLocation", reply); } -void Ledger::updateLocationFailure(QNetworkReply& reply) { failResponse("updateLocation", reply); } +void Ledger::updateLocationSuccess(QNetworkReply* reply) { apiResponse("updateLocation", reply); } +void Ledger::updateLocationFailure(QNetworkReply* reply) { failResponse("updateLocation", reply); } void Ledger::updateLocation(const QString& asset_id, const QString& location, const bool& alsoUpdateSiblings, const bool controlledFailure) { auto wallet = DependencyManager::get(); auto walletScriptingInterface = DependencyManager::get(); @@ -349,11 +349,11 @@ void Ledger::updateLocation(const QString& asset_id, const QString& location, co } } -void Ledger::certificateInfoSuccess(QNetworkReply& reply) { +void Ledger::certificateInfoSuccess(QNetworkReply* reply) { auto wallet = DependencyManager::get(); auto accountManager = DependencyManager::get(); - QByteArray response = reply.readAll(); + QByteArray response = reply->readAll(); QJsonObject replyObject = QJsonDocument::fromJson(response).object(); QStringList keys = wallet->listPublicKeys(); @@ -366,7 +366,7 @@ void Ledger::certificateInfoSuccess(QNetworkReply& reply) { qInfo(commerce) << "certificateInfo" << "response" << QJsonDocument(replyObject).toJson(QJsonDocument::Compact); emit certificateInfoResult(replyObject); } -void Ledger::certificateInfoFailure(QNetworkReply& reply) { +void Ledger::certificateInfoFailure(QNetworkReply* reply) { emit certificateInfoResult(failResponse("certificateInfo", reply)); } void Ledger::certificateInfo(const QString& certificateId) { diff --git a/interface/src/commerce/Ledger.h b/interface/src/commerce/Ledger.h index 8a8fd2630a..ba2f167f4b 100644 --- a/interface/src/commerce/Ledger.h +++ b/interface/src/commerce/Ledger.h @@ -65,36 +65,36 @@ signals: void updateCertificateStatus(const QString& certID, uint certStatus); public slots: - void buySuccess(QNetworkReply& reply); - void buyFailure(QNetworkReply& reply); - void receiveAtSuccess(QNetworkReply& reply); - void receiveAtFailure(QNetworkReply& reply); - void balanceSuccess(QNetworkReply& reply); - void balanceFailure(QNetworkReply& reply); - void inventorySuccess(QNetworkReply& reply); - void inventoryFailure(QNetworkReply& reply); - void historySuccess(QNetworkReply& reply); - void historyFailure(QNetworkReply& reply); - void accountSuccess(QNetworkReply& reply); - void accountFailure(QNetworkReply& reply); - void updateLocationSuccess(QNetworkReply& reply); - void updateLocationFailure(QNetworkReply& reply); - void certificateInfoSuccess(QNetworkReply& reply); - void certificateInfoFailure(QNetworkReply& reply); - void transferAssetToNodeSuccess(QNetworkReply& reply); - void transferAssetToNodeFailure(QNetworkReply& reply); - void transferAssetToUsernameSuccess(QNetworkReply& reply); - void transferAssetToUsernameFailure(QNetworkReply& reply); - void alreadyOwnedSuccess(QNetworkReply& reply); - void alreadyOwnedFailure(QNetworkReply& reply); - void availableUpdatesSuccess(QNetworkReply& reply); - void availableUpdatesFailure(QNetworkReply& reply); - void updateItemSuccess(QNetworkReply& reply); - void updateItemFailure(QNetworkReply& reply); + void buySuccess(QNetworkReply* reply); + void buyFailure(QNetworkReply* reply); + void receiveAtSuccess(QNetworkReply* reply); + void receiveAtFailure(QNetworkReply* reply); + void balanceSuccess(QNetworkReply* reply); + void balanceFailure(QNetworkReply* reply); + void inventorySuccess(QNetworkReply* reply); + void inventoryFailure(QNetworkReply* reply); + void historySuccess(QNetworkReply* reply); + void historyFailure(QNetworkReply* reply); + void accountSuccess(QNetworkReply* reply); + void accountFailure(QNetworkReply* reply); + void updateLocationSuccess(QNetworkReply* reply); + void updateLocationFailure(QNetworkReply* reply); + void certificateInfoSuccess(QNetworkReply* reply); + void certificateInfoFailure(QNetworkReply* reply); + void transferAssetToNodeSuccess(QNetworkReply* reply); + void transferAssetToNodeFailure(QNetworkReply* reply); + void transferAssetToUsernameSuccess(QNetworkReply* reply); + void transferAssetToUsernameFailure(QNetworkReply* reply); + void alreadyOwnedSuccess(QNetworkReply* reply); + void alreadyOwnedFailure(QNetworkReply* reply); + void availableUpdatesSuccess(QNetworkReply* reply); + void availableUpdatesFailure(QNetworkReply* reply); + void updateItemSuccess(QNetworkReply* reply); + void updateItemFailure(QNetworkReply* reply); private: - QJsonObject apiResponse(const QString& label, QNetworkReply& reply); - QJsonObject failResponse(const QString& label, QNetworkReply& reply); + QJsonObject apiResponse(const QString& label, QNetworkReply* reply); + QJsonObject failResponse(const QString& label, QNetworkReply* reply); void send(const QString& endpoint, const QString& success, const QString& fail, QNetworkAccessManager::Operation method, AccountManagerAuth::Type authType, QJsonObject request); void keysQuery(const QString& endpoint, const QString& success, const QString& fail, QJsonObject& extraRequestParams); void keysQuery(const QString& endpoint, const QString& success, const QString& fail); diff --git a/interface/src/scripting/SettingsScriptingInterface.cpp b/interface/src/scripting/SettingsScriptingInterface.cpp index 2f14c33dc7..afafe1a350 100644 --- a/interface/src/scripting/SettingsScriptingInterface.cpp +++ b/interface/src/scripting/SettingsScriptingInterface.cpp @@ -35,5 +35,8 @@ QVariant SettingsScriptingInterface::getValue(const QString& setting, const QVar } void SettingsScriptingInterface::setValue(const QString& setting, const QVariant& value) { - Setting::Handle(setting).set(value); + // Make a deep-copy of the string. + // Dangling pointers can occur with QStrings that are implicitly shared from a QScriptEngine. + QString deepCopy = QString::fromUtf16(setting.utf16()); + Setting::Handle(deepCopy).set(value); } diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index 39a5849d85..4d8592a9d3 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -113,9 +113,8 @@ void LoginDialog::linkSteam() { } JSONCallbackParameters callbackParams; - callbackParams.jsonCallbackReceiver = this; + callbackParams.callbackReceiver = this; callbackParams.jsonCallbackMethod = "linkCompleted"; - callbackParams.errorCallbackReceiver = this; callbackParams.errorCallbackMethod = "linkFailed"; const QString LINK_STEAM_PATH = "api/v1/user/steam/link"; @@ -141,9 +140,8 @@ void LoginDialog::createAccountFromStream(QString username) { } JSONCallbackParameters callbackParams; - callbackParams.jsonCallbackReceiver = this; + callbackParams.callbackReceiver = this; callbackParams.jsonCallbackMethod = "createCompleted"; - callbackParams.errorCallbackReceiver = this; callbackParams.errorCallbackMethod = "createFailed"; const QString CREATE_ACCOUNT_FROM_STEAM_PATH = "api/v1/user/steam/create"; @@ -185,28 +183,27 @@ void LoginDialog::openUrl(const QString& url) const { } } -void LoginDialog::linkCompleted(QNetworkReply& reply) { +void LoginDialog::linkCompleted(QNetworkReply* reply) { emit handleLinkCompleted(); } -void LoginDialog::linkFailed(QNetworkReply& reply) { - emit handleLinkFailed(reply.errorString()); +void LoginDialog::linkFailed(QNetworkReply* reply) { + emit handleLinkFailed(reply->errorString()); } -void LoginDialog::createCompleted(QNetworkReply& reply) { +void LoginDialog::createCompleted(QNetworkReply* reply) { emit handleCreateCompleted(); } -void LoginDialog::createFailed(QNetworkReply& reply) { - emit handleCreateFailed(reply.errorString()); +void LoginDialog::createFailed(QNetworkReply* reply) { + emit handleCreateFailed(reply->errorString()); } void LoginDialog::signup(const QString& email, const QString& username, const QString& password) { JSONCallbackParameters callbackParams; - callbackParams.jsonCallbackReceiver = this; + callbackParams.callbackReceiver = this; callbackParams.jsonCallbackMethod = "signupCompleted"; - callbackParams.errorCallbackReceiver = this; callbackParams.errorCallbackMethod = "signupFailed"; QJsonObject payload; @@ -228,7 +225,7 @@ void LoginDialog::signup(const QString& email, const QString& username, const QS QJsonDocument(payload).toJson()); } -void LoginDialog::signupCompleted(QNetworkReply& reply) { +void LoginDialog::signupCompleted(QNetworkReply* reply) { emit handleSignupCompleted(); } @@ -242,10 +239,10 @@ QString errorStringFromAPIObject(const QJsonValue& apiObject) { } } -void LoginDialog::signupFailed(QNetworkReply& reply) { +void LoginDialog::signupFailed(QNetworkReply* reply) { // parse the returned JSON to see what the problem was - auto jsonResponse = QJsonDocument::fromJson(reply.readAll()); + auto jsonResponse = QJsonDocument::fromJson(reply->readAll()); static const QString RESPONSE_DATA_KEY = "data"; diff --git a/interface/src/ui/LoginDialog.h b/interface/src/ui/LoginDialog.h index 5ebf866fbd..ad8cab9699 100644 --- a/interface/src/ui/LoginDialog.h +++ b/interface/src/ui/LoginDialog.h @@ -42,14 +42,14 @@ signals: void handleSignupFailed(QString errorString); public slots: - void linkCompleted(QNetworkReply& reply); - void linkFailed(QNetworkReply& reply); + void linkCompleted(QNetworkReply* reply); + void linkFailed(QNetworkReply* reply); - void createCompleted(QNetworkReply& reply); - void createFailed(QNetworkReply& reply); + void createCompleted(QNetworkReply* reply); + void createFailed(QNetworkReply* reply); - void signupCompleted(QNetworkReply& reply); - void signupFailed(QNetworkReply& reply); + void signupCompleted(QNetworkReply* reply); + void signupFailed(QNetworkReply* reply); protected slots: Q_INVOKABLE bool isSteamRunning() const; diff --git a/interface/src/ui/OverlayConductor.cpp b/interface/src/ui/OverlayConductor.cpp index d131bb3467..e27001567f 100644 --- a/interface/src/ui/OverlayConductor.cpp +++ b/interface/src/ui/OverlayConductor.cpp @@ -88,38 +88,24 @@ void OverlayConductor::update(float dt) { _hmdMode = false; } - bool isAtRest = updateAvatarIsAtRest(); - bool isMoving = !isAtRest; - bool shouldRecenter = false; - if (_flags & SuppressedByMove) { - if (!isMoving) { - _flags &= ~SuppressedByMove; - shouldRecenter = true; - } - } else { - if (myAvatar->getClearOverlayWhenMoving() && isMoving) { - _flags |= SuppressedByMove; - } - } - - if (_flags & SuppressedByHead) { - if (isAtRest) { - _flags &= ~SuppressedByHead; + if (_suppressedByHead) { + if (updateAvatarIsAtRest()) { + _suppressedByHead = false; shouldRecenter = true; } } else { if (_hmdMode && headOutsideOverlay()) { - _flags |= SuppressedByHead; + _suppressedByHead = true; } } - bool targetVisible = Menu::getInstance()->isOptionChecked(MenuOption::Overlays) && (0 == (_flags & SuppressMask)); + bool targetVisible = Menu::getInstance()->isOptionChecked(MenuOption::Overlays) && !_suppressedByHead; if (targetVisible != currentVisible) { offscreenUi->setPinned(!targetVisible); } - if (shouldRecenter && !_flags) { + if (shouldRecenter && !_suppressedByHead) { centerUI(); } } diff --git a/interface/src/ui/OverlayConductor.h b/interface/src/ui/OverlayConductor.h index cf69c32fc5..b47e23d28a 100644 --- a/interface/src/ui/OverlayConductor.h +++ b/interface/src/ui/OverlayConductor.h @@ -25,13 +25,7 @@ private: bool headOutsideOverlay() const; bool updateAvatarIsAtRest(); - enum SupressionFlags { - SuppressedByMove = 0x01, - SuppressedByHead = 0x02, - SuppressMask = 0x03, - }; - - uint8_t _flags { SuppressedByMove }; + bool _suppressedByHead { false }; bool _hmdMode { false }; // used by updateAvatarIsAtRest diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 3d3c432e92..e7c010fc31 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -161,12 +161,6 @@ void setupPreferences() { preferences->addPreference(new CheckPreference(UI_CATEGORY, "Use reticle cursor instead of arrow", getter, setter)); } - { - auto getter = [=]()->bool { return myAvatar->getClearOverlayWhenMoving(); }; - auto setter = [=](bool value) { myAvatar->setClearOverlayWhenMoving(value); }; - preferences->addPreference(new CheckPreference(UI_CATEGORY, "Clear overlays when moving", getter, setter)); - } - static const QString VIEW_CATEGORY{ "View" }; { auto getter = [=]()->float { return myAvatar->getRealWorldFieldOfView(); }; diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index efcc85b23e..60c039ce1f 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -493,7 +493,7 @@ void Snapshot::uploadSnapshot(const QString& filename, const QUrl& href) { multiPart->append(imagePart); auto accountManager = DependencyManager::get(); - JSONCallbackParameters callbackParams(uploader, "uploadSuccess", uploader, "uploadFailure"); + JSONCallbackParameters callbackParams(uploader, "uploadSuccess", "uploadFailure"); accountManager->sendRequest(SNAPSHOT_UPLOAD_URL, AccountManagerAuth::Required, QNetworkAccessManager::PostOperation, callbackParams, nullptr, multiPart); diff --git a/interface/src/ui/SnapshotUploader.cpp b/interface/src/ui/SnapshotUploader.cpp index 4613871d25..694d0fa8f8 100644 --- a/interface/src/ui/SnapshotUploader.cpp +++ b/interface/src/ui/SnapshotUploader.cpp @@ -23,11 +23,11 @@ SnapshotUploader::SnapshotUploader(QUrl inWorldLocation, QString pathname) : _pathname(pathname) { } -void SnapshotUploader::uploadSuccess(QNetworkReply& reply) { +void SnapshotUploader::uploadSuccess(QNetworkReply* reply) { const QString STORY_UPLOAD_URL = "/api/v1/user_stories"; // parse the reply for the thumbnail_url - QByteArray contents = reply.readAll(); + QByteArray contents = reply->readAll(); QJsonParseError jsonError; auto doc = QJsonDocument::fromJson(contents, &jsonError); if (jsonError.error == QJsonParseError::NoError) { @@ -60,7 +60,7 @@ void SnapshotUploader::uploadSuccess(QNetworkReply& reply) { rootObject.insert("user_story", userStoryObject); auto accountManager = DependencyManager::get(); - JSONCallbackParameters callbackParams(this, "createStorySuccess", this, "createStoryFailure"); + JSONCallbackParameters callbackParams(this, "createStorySuccess", "createStoryFailure"); accountManager->sendRequest(STORY_UPLOAD_URL, AccountManagerAuth::Required, @@ -74,11 +74,11 @@ void SnapshotUploader::uploadSuccess(QNetworkReply& reply) { } } -void SnapshotUploader::uploadFailure(QNetworkReply& reply) { - QString replyString = reply.readAll(); - qDebug() << "Error " << reply.errorString() << " uploading snapshot " << _pathname << " from " << _inWorldLocation; +void SnapshotUploader::uploadFailure(QNetworkReply* reply) { + QString replyString = reply->readAll(); + qDebug() << "Error " << reply->errorString() << " uploading snapshot " << _pathname << " from " << _inWorldLocation; if (replyString.size() == 0) { - replyString = reply.errorString(); + replyString = reply->errorString(); } replyString = replyString.left(1000); // Only print first 1000 characters of error qDebug() << "Snapshot upload reply error (truncated):" << replyString; @@ -86,17 +86,17 @@ void SnapshotUploader::uploadFailure(QNetworkReply& reply) { this->deleteLater(); } -void SnapshotUploader::createStorySuccess(QNetworkReply& reply) { - QString replyString = reply.readAll(); +void SnapshotUploader::createStorySuccess(QNetworkReply* reply) { + QString replyString = reply->readAll(); emit DependencyManager::get()->snapshotShared(false, replyString); this->deleteLater(); } -void SnapshotUploader::createStoryFailure(QNetworkReply& reply) { - QString replyString = reply.readAll(); - qDebug() << "Error " << reply.errorString() << " uploading snapshot story " << _pathname << " from " << _inWorldLocation; +void SnapshotUploader::createStoryFailure(QNetworkReply* reply) { + QString replyString = reply->readAll(); + qDebug() << "Error " << reply->errorString() << " uploading snapshot story " << _pathname << " from " << _inWorldLocation; if (replyString.size() == 0) { - replyString = reply.errorString(); + replyString = reply->errorString(); } replyString = replyString.left(1000); // Only print first 1000 characters of error qDebug() << "Snapshot story upload reply error (truncated):" << replyString; diff --git a/interface/src/ui/SnapshotUploader.h b/interface/src/ui/SnapshotUploader.h index ae6d5d55ca..d8e72730c7 100644 --- a/interface/src/ui/SnapshotUploader.h +++ b/interface/src/ui/SnapshotUploader.h @@ -21,12 +21,12 @@ class SnapshotUploader : public QObject { public: SnapshotUploader(QUrl inWorldLocation, QString pathname); public slots: - void uploadSuccess(QNetworkReply& reply); - void uploadFailure(QNetworkReply& reply); - void createStorySuccess(QNetworkReply& reply); - void createStoryFailure(QNetworkReply& reply); + void uploadSuccess(QNetworkReply* reply); + void uploadFailure(QNetworkReply* reply); + void createStorySuccess(QNetworkReply* reply); + void createStoryFailure(QNetworkReply* reply); private: QUrl _inWorldLocation; QString _pathname; }; -#endif // hifi_SnapshotUploader_h \ No newline at end of file +#endif // hifi_SnapshotUploader_h diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index a5f79290cd..a6f0416a30 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -1426,6 +1426,8 @@ bool AudioClient::setIsStereoInput(bool isStereoInput) { // restart the input device switchInputToAudioDevice(_inputDeviceInfo); + + emit isStereoInputChanged(_isStereoInput); } return stereoInputChanged; @@ -1463,6 +1465,8 @@ void AudioClient::outputFormatChanged() { } bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo inputDeviceInfo, bool isShutdownRequest) { + Q_ASSERT_X(QThread::currentThread() == thread(), Q_FUNC_INFO, "Function invoked on wrong thread"); + qCDebug(audioclient) << __FUNCTION__ << "inputDeviceInfo: [" << inputDeviceInfo.deviceName() << "]"; bool supportedFormat = false; @@ -1663,6 +1667,8 @@ void AudioClient::outputNotify() { } bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo outputDeviceInfo, bool isShutdownRequest) { + Q_ASSERT_X(QThread::currentThread() == thread(), Q_FUNC_INFO, "Function invoked on wrong thread"); + qCDebug(audioclient) << "AudioClient::switchOutputToAudioDevice() outputDeviceInfo: [" << outputDeviceInfo.deviceName() << "]"; bool supportedFormat = false; @@ -2021,7 +2027,7 @@ void AudioClient::setAvatarBoundingBoxParameters(glm::vec3 corner, glm::vec3 sca void AudioClient::startThread() { - moveToNewNamedThread(this, "Audio Thread", [this] { start(); }); + moveToNewNamedThread(this, "Audio Thread", [this] { start(); }, QThread::TimeCriticalPriority); } void AudioClient::setInputVolume(float volume, bool emitSignal) { diff --git a/libraries/audio/src/AbstractAudioInterface.h b/libraries/audio/src/AbstractAudioInterface.h index 30cbceeb0e..bbfd79d0aa 100644 --- a/libraries/audio/src/AbstractAudioInterface.h +++ b/libraries/audio/src/AbstractAudioInterface.h @@ -44,6 +44,9 @@ public slots: virtual bool setIsStereoInput(bool stereo) = 0; virtual bool isStereoInput() = 0; + +signals: + void isStereoInputChanged(bool isStereo); }; Q_DECLARE_METATYPE(AbstractAudioInterface*) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index a99838d810..843235c0e1 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1338,6 +1338,9 @@ void Avatar::scaleVectorRelativeToPosition(glm::vec3 &positionToScale) const { } void Avatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { + if (!isMyAvatar()) { + createOrb(); + } AvatarData::setSkeletonModelURL(skeletonModelURL); if (QThread::currentThread() == thread()) { _skeletonModel->setURL(_skeletonModelURL); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 98246330c4..bb9d6d8cc9 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -23,7 +23,6 @@ #include #include - #include "Head.h" #include "SkeletonModel.h" #include "Rig.h" @@ -41,7 +40,6 @@ static const float SCALING_RATIO = .05f; extern const float CHAT_MESSAGE_SCALE; extern const float CHAT_MESSAGE_HEIGHT; - enum ScreenTintLayer { SCREEN_TINT_BEFORE_LANDSCAPE = 0, SCREEN_TINT_BEFORE_AVATARS, @@ -69,7 +67,7 @@ public: static void setShowNamesAboveHeads(bool show); explicit Avatar(QThread* thread); - ~Avatar(); + virtual ~Avatar(); virtual void instantiableAvatar() = 0; @@ -109,6 +107,7 @@ public: float getLODDistance() const; virtual bool isMyAvatar() const override { return false; } + virtual void createOrb() { } virtual QVector getJointRotations() const override; using AvatarData::getJointRotation; @@ -167,8 +166,8 @@ public: virtual int parseDataFromBuffer(const QByteArray& buffer) override; - static void renderJointConnectingCone( gpu::Batch& batch, glm::vec3 position1, glm::vec3 position2, - float radius1, float radius2, const glm::vec4& color); + static void renderJointConnectingCone(gpu::Batch& batch, glm::vec3 position1, glm::vec3 position2, + float radius1, float radius2, const glm::vec4& color); virtual void applyCollision(const glm::vec3& contactPoint, const glm::vec3& penetration) { } @@ -235,7 +234,7 @@ public: /// Scales a world space position vector relative to the avatar position and scale /// \param vector position to be scaled. Will store the result - void scaleVectorRelativeToPosition(glm::vec3 &positionToScale) const; + void scaleVectorRelativeToPosition(glm::vec3& positionToScale) const; void slamPosition(const glm::vec3& position); virtual void updateAttitude(const glm::quat& orientation) override; @@ -254,7 +253,6 @@ public: void setPositionViaScript(const glm::vec3& position) override; void setOrientationViaScript(const glm::quat& orientation) override; - /**jsdoc * @function MyAvatar.getParentID * @returns {Uuid} @@ -283,7 +281,6 @@ public: // This calls through to the SpatiallyNestable versions, but is here to expose these to JavaScript. Q_INVOKABLE virtual void setParentJointIndex(quint16 parentJointIndex) override; - /**jsdoc * Returns an array of joints, where each joint is an object containing name, index, and parentIndex fields. * @function MyAvatar.getSkeleton @@ -349,7 +346,6 @@ public: // not all subclasses of AvatarData have access to this data. virtual bool canMeasureEyeHeight() const override { return true; } - virtual float getModelScale() const { return _modelScale; } virtual void setModelScale(float scale) { _modelScale = scale; } virtual glm::vec3 scaleForChildren() const override { return glm::vec3(getModelScale()); } diff --git a/libraries/avatars-renderer/src/avatars-renderer/OtherAvatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/OtherAvatar.cpp deleted file mode 100644 index 7678c03276..0000000000 --- a/libraries/avatars-renderer/src/avatars-renderer/OtherAvatar.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// -// Created by Bradley Austin Davis on 2017/04/27 -// Copyright 2013-2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "OtherAvatar.h" - -OtherAvatar::OtherAvatar(QThread* thread) : Avatar(thread) { - // give the pointer to our head to inherited _headData variable from AvatarData - _headData = new Head(this); - _skeletonModel = std::make_shared(this, nullptr); - _skeletonModel->setLoadingPriority(OTHERAVATAR_LOADING_PRIORITY); - connect(_skeletonModel.get(), &Model::setURLFinished, this, &Avatar::setModelURLFinished); - connect(_skeletonModel.get(), &Model::rigReady, this, &Avatar::rigReady); - connect(_skeletonModel.get(), &Model::rigReset, this, &Avatar::rigReset); -} diff --git a/libraries/avatars-renderer/src/avatars-renderer/OtherAvatar.h b/libraries/avatars-renderer/src/avatars-renderer/OtherAvatar.h deleted file mode 100644 index df09d7fd99..0000000000 --- a/libraries/avatars-renderer/src/avatars-renderer/OtherAvatar.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// Created by Bradley Austin Davis on 2017/04/27 -// Copyright 2013-2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_OtherAvatar_h -#define hifi_OtherAvatar_h - -#include "Avatar.h" - -class OtherAvatar : public Avatar { -public: - explicit OtherAvatar(QThread* thread); - virtual void instantiableAvatar() override {}; -}; - -#endif // hifi_OtherAvatar_h diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index b830313723..d0efed3df4 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1816,7 +1816,6 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS } } - float clusterScale = extractUniformScale(fbxCluster.inverseBindMatrix); glm::mat4 meshToJoint = glm::inverse(joint.bindTransform) * modelTransform; ShapeVertices& points = shapeVertices.at(jointIndex); @@ -1832,7 +1831,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS if (weight >= EXPANSION_WEIGHT_THRESHOLD) { // transform to joint-frame and save for later const glm::mat4 vertexTransform = meshToJoint * glm::translate(extracted.mesh.vertices.at(newIndex)); - points.push_back(extractTranslation(vertexTransform) * clusterScale); + points.push_back(extractTranslation(vertexTransform)); } // look for an unused slot in the weights vector @@ -1886,12 +1885,11 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS FBXJoint& joint = geometry.joints[jointIndex]; // transform cluster vertices to joint-frame and save for later - float clusterScale = extractUniformScale(firstFBXCluster.inverseBindMatrix); glm::mat4 meshToJoint = glm::inverse(joint.bindTransform) * modelTransform; ShapeVertices& points = shapeVertices.at(jointIndex); foreach (const glm::vec3& vertex, extracted.mesh.vertices) { const glm::mat4 vertexTransform = meshToJoint * glm::translate(vertex); - points.push_back(extractTranslation(vertexTransform) * clusterScale); + points.push_back(extractTranslation(vertexTransform)); } // Apply geometric offset, if present, by transforming the vertices directly diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index 05f0ec12b5..5b3196a2bf 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -46,21 +47,18 @@ Q_DECLARE_METATYPE(JSONCallbackParameters) const QString ACCOUNTS_GROUP = "accounts"; -JSONCallbackParameters::JSONCallbackParameters(QObject* jsonCallbackReceiver, const QString& jsonCallbackMethod, - QObject* errorCallbackReceiver, const QString& errorCallbackMethod, - QObject* updateReceiver, const QString& updateSlot) : - jsonCallbackReceiver(jsonCallbackReceiver), +JSONCallbackParameters::JSONCallbackParameters(QObject* callbackReceiver, + const QString& jsonCallbackMethod, + const QString& errorCallbackMethod) : + callbackReceiver(callbackReceiver), jsonCallbackMethod(jsonCallbackMethod), - errorCallbackReceiver(errorCallbackReceiver), - errorCallbackMethod(errorCallbackMethod), - updateReciever(updateReceiver), - updateSlot(updateSlot) + errorCallbackMethod(errorCallbackMethod) { } -QJsonObject AccountManager::dataObjectFromResponse(QNetworkReply &requestReply) { - QJsonObject jsonObject = QJsonDocument::fromJson(requestReply.readAll()).object(); +QJsonObject AccountManager::dataObjectFromResponse(QNetworkReply* requestReply) { + QJsonObject jsonObject = QJsonDocument::fromJson(requestReply->readAll()).object(); static const QString STATUS_KEY = "status"; static const QString DATA_KEY = "data"; @@ -74,8 +72,7 @@ QJsonObject AccountManager::dataObjectFromResponse(QNetworkReply &requestReply) AccountManager::AccountManager(UserAgentGetter userAgentGetter) : _userAgentGetter(userAgentGetter), - _authURL(), - _pendingCallbackMap() + _authURL() { qRegisterMetaType("OAuthAccessToken"); qRegisterMetaTypeStreamOperators("OAuthAccessToken"); @@ -323,75 +320,66 @@ void AccountManager::sendRequest(const QString& path, } } - - if (!callbackParams.isEmpty()) { - // if we have information for a callback, insert the callbackParams into our local map - _pendingCallbackMap.insert(networkReply, callbackParams); - - if (callbackParams.updateReciever && !callbackParams.updateSlot.isEmpty()) { - callbackParams.updateReciever->connect(networkReply, SIGNAL(uploadProgress(qint64, qint64)), - callbackParams.updateSlot.toStdString().c_str()); + connect(networkReply, &QNetworkReply::finished, this, [this, networkReply] { + // double check if the finished network reply had a session ID in the header and make + // sure that our session ID matches that value if so + if (networkReply->hasRawHeader(METAVERSE_SESSION_ID_HEADER)) { + _sessionID = networkReply->rawHeader(METAVERSE_SESSION_ID_HEADER); } + }); + + + if (callbackParams.isEmpty()) { + connect(networkReply, &QNetworkReply::finished, networkReply, &QNetworkReply::deleteLater); + } else { + // There's a cleaner way to fire the JSON/error callbacks below and ensure that deleteLater is called for the + // request reply - unfortunately it requires Qt 5.10 which the Android build does not support as of 06/26/18 + + connect(networkReply, &QNetworkReply::finished, callbackParams.callbackReceiver, + [callbackParams, networkReply] { + if (networkReply->error() == QNetworkReply::NoError) { + if (!callbackParams.jsonCallbackMethod.isEmpty()) { + bool invoked = QMetaObject::invokeMethod(callbackParams.callbackReceiver, + qPrintable(callbackParams.jsonCallbackMethod), + Q_ARG(QNetworkReply*, networkReply)); + + if (!invoked) { + QString error = "Could not invoke " + callbackParams.jsonCallbackMethod + " with QNetworkReply* " + + "on callbackReceiver."; + qCWarning(networking) << error; + Q_ASSERT_X(invoked, "AccountManager::passErrorToCallback", qPrintable(error)); + } + } else { + if (VERBOSE_HTTP_REQUEST_DEBUGGING) { + qCDebug(networking) << "Received JSON response from metaverse API that has no matching callback."; + qCDebug(networking) << QJsonDocument::fromJson(networkReply->readAll()); + } + } + } else { + if (!callbackParams.errorCallbackMethod.isEmpty()) { + bool invoked = QMetaObject::invokeMethod(callbackParams.callbackReceiver, + qPrintable(callbackParams.errorCallbackMethod), + Q_ARG(QNetworkReply*, networkReply)); + + if (!invoked) { + QString error = "Could not invoke " + callbackParams.errorCallbackMethod + " with QNetworkReply* " + + "on callbackReceiver."; + qCWarning(networking) << error; + Q_ASSERT_X(invoked, "AccountManager::passErrorToCallback", qPrintable(error)); + } + + } else { + if (VERBOSE_HTTP_REQUEST_DEBUGGING) { + qCDebug(networking) << "Received error response from metaverse API that has no matching callback."; + qCDebug(networking) << "Error" << networkReply->error() << "-" << networkReply->errorString(); + qCDebug(networking) << networkReply->readAll(); + } + } + } + + networkReply->deleteLater(); + }); } - - // if we ended up firing of a request, hook up to it now - connect(networkReply, SIGNAL(finished()), SLOT(processReply())); - } -} - -void AccountManager::processReply() { - QNetworkReply* requestReply = reinterpret_cast(sender()); - - if (requestReply->error() == QNetworkReply::NoError) { - if (requestReply->hasRawHeader(METAVERSE_SESSION_ID_HEADER)) { - _sessionID = requestReply->rawHeader(METAVERSE_SESSION_ID_HEADER); - } - passSuccessToCallback(requestReply); - } else { - passErrorToCallback(requestReply); - } - requestReply->deleteLater(); -} - -void AccountManager::passSuccessToCallback(QNetworkReply* requestReply) { - JSONCallbackParameters callbackParams = _pendingCallbackMap.value(requestReply); - - if (callbackParams.jsonCallbackReceiver) { - // invoke the right method on the callback receiver - QMetaObject::invokeMethod(callbackParams.jsonCallbackReceiver, qPrintable(callbackParams.jsonCallbackMethod), - Q_ARG(QNetworkReply&, *requestReply)); - - // remove the related reply-callback group from the map - _pendingCallbackMap.remove(requestReply); - - } else { - if (VERBOSE_HTTP_REQUEST_DEBUGGING) { - qCDebug(networking) << "Received JSON response from metaverse API that has no matching callback."; - qCDebug(networking) << QJsonDocument::fromJson(requestReply->readAll()); - } - - requestReply->deleteLater(); - } -} - -void AccountManager::passErrorToCallback(QNetworkReply* requestReply) { - JSONCallbackParameters callbackParams = _pendingCallbackMap.value(requestReply); - - if (callbackParams.errorCallbackReceiver) { - // invoke the right method on the callback receiver - QMetaObject::invokeMethod(callbackParams.errorCallbackReceiver, qPrintable(callbackParams.errorCallbackMethod), - Q_ARG(QNetworkReply&, *requestReply)); - - // remove the related reply-callback group from the map - _pendingCallbackMap.remove(requestReply); - } else { - if (VERBOSE_HTTP_REQUEST_DEBUGGING) { - qCDebug(networking) << "Received error response from metaverse API that has no matching callback."; - qCDebug(networking) << "Error" << requestReply->error() << "-" << requestReply->errorString(); - qCDebug(networking) << requestReply->readAll(); - } - - requestReply->deleteLater(); } } @@ -817,16 +805,15 @@ void AccountManager::processGeneratedKeypair(QByteArray publicKey, QByteArray pr // setup callback parameters so we know once the keypair upload has succeeded or failed JSONCallbackParameters callbackParameters; - callbackParameters.jsonCallbackReceiver = this; + callbackParameters.callbackReceiver = this; callbackParameters.jsonCallbackMethod = "publicKeyUploadSucceeded"; - callbackParameters.errorCallbackReceiver = this; callbackParameters.errorCallbackMethod = "publicKeyUploadFailed"; sendRequest(uploadPath, AccountManagerAuth::Optional, QNetworkAccessManager::PutOperation, callbackParameters, QByteArray(), requestMultiPart); } -void AccountManager::publicKeyUploadSucceeded(QNetworkReply& reply) { +void AccountManager::publicKeyUploadSucceeded(QNetworkReply* reply) { qCDebug(networking) << "Uploaded public key to Metaverse API. RSA keypair generation is completed."; // public key upload complete - store the matching private key and persist the account to settings @@ -838,23 +825,17 @@ void AccountManager::publicKeyUploadSucceeded(QNetworkReply& reply) { _isWaitingForKeypairResponse = false; emit newKeypair(); - - // delete the reply object now that we are done with it - reply.deleteLater(); } -void AccountManager::publicKeyUploadFailed(QNetworkReply& reply) { +void AccountManager::publicKeyUploadFailed(QNetworkReply* reply) { // the public key upload has failed - qWarning() << "Public key upload failed from AccountManager" << reply.errorString(); + qWarning() << "Public key upload failed from AccountManager" << reply->errorString(); // we aren't waiting for a response any longer _isWaitingForKeypairResponse = false; // clear our pending private key _pendingPrivateKey.clear(); - - // delete the reply object now that we are done with it - reply.deleteLater(); } void AccountManager::handleKeypairGenerationError() { diff --git a/libraries/networking/src/AccountManager.h b/libraries/networking/src/AccountManager.h index 9068966512..a79b69fe2b 100644 --- a/libraries/networking/src/AccountManager.h +++ b/libraries/networking/src/AccountManager.h @@ -28,18 +28,14 @@ class JSONCallbackParameters { public: - JSONCallbackParameters(QObject* jsonCallbackReceiver = nullptr, const QString& jsonCallbackMethod = QString(), - QObject* errorCallbackReceiver = nullptr, const QString& errorCallbackMethod = QString(), - QObject* updateReceiver = nullptr, const QString& updateSlot = QString()); + JSONCallbackParameters(QObject* callbackReceiver = nullptr, const QString& jsonCallbackMethod = QString(), + const QString& errorCallbackMethod = QString()); - bool isEmpty() const { return !jsonCallbackReceiver && !errorCallbackReceiver; } + bool isEmpty() const { return !callbackReceiver; } - QObject* jsonCallbackReceiver; + QObject* callbackReceiver; QString jsonCallbackMethod; - QObject* errorCallbackReceiver; QString errorCallbackMethod; - QObject* updateReciever; - QString updateSlot; }; namespace AccountManagerAuth { @@ -90,7 +86,7 @@ public: DataServerAccountInfo& getAccountInfo() { return _accountInfo; } void setAccountInfo(const DataServerAccountInfo &newAccountInfo); - static QJsonObject dataObjectFromResponse(QNetworkReply& requestReply); + static QJsonObject dataObjectFromResponse(QNetworkReply* requestReply); QUuid getSessionID() const { return _sessionID; } void setSessionID(const QUuid& sessionID); @@ -126,11 +122,10 @@ signals: void newKeypair(); private slots: - void processReply(); void handleKeypairGenerationError(); void processGeneratedKeypair(QByteArray publicKey, QByteArray privateKey); - void publicKeyUploadSucceeded(QNetworkReply& reply); - void publicKeyUploadFailed(QNetworkReply& reply); + void publicKeyUploadSucceeded(QNetworkReply* reply); + void publicKeyUploadFailed(QNetworkReply* reply); void generateNewKeypair(bool isUserKeypair = true, const QUuid& domainID = QUuid()); private: @@ -146,8 +141,6 @@ private: UserAgentGetter _userAgentGetter; QUrl _authURL; - - QMap _pendingCallbackMap; DataServerAccountInfo _accountInfo; bool _isWaitingForTokenRefresh { false }; diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 317be194b8..3fe75c5495 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -215,9 +215,8 @@ const JSONCallbackParameters& AddressManager::apiCallbackParameters() { static JSONCallbackParameters callbackParams; if (!hasSetupParameters) { - callbackParams.jsonCallbackReceiver = this; + callbackParams.callbackReceiver = this; callbackParams.jsonCallbackMethod = "handleAPIResponse"; - callbackParams.errorCallbackReceiver = this; callbackParams.errorCallbackMethod = "handleAPIError"; } @@ -377,8 +376,8 @@ void AddressManager::handleLookupString(const QString& lookupString, bool fromSu const QString DATA_OBJECT_DOMAIN_KEY = "domain"; -void AddressManager::handleAPIResponse(QNetworkReply& requestReply) { - QJsonObject responseObject = QJsonDocument::fromJson(requestReply.readAll()).object(); +void AddressManager::handleAPIResponse(QNetworkReply* requestReply) { + QJsonObject responseObject = QJsonDocument::fromJson(requestReply->readAll()).object(); QJsonObject dataObject = responseObject["data"].toObject(); // Lookup succeeded, don't keep re-trying it (especially on server restarts) @@ -396,7 +395,7 @@ void AddressManager::handleAPIResponse(QNetworkReply& requestReply) { const char OVERRIDE_PATH_KEY[] = "override_path"; const char LOOKUP_TRIGGER_KEY[] = "lookup_trigger"; -void AddressManager::goToAddressFromObject(const QVariantMap& dataObject, const QNetworkReply& reply) { +void AddressManager::goToAddressFromObject(const QVariantMap& dataObject, const QNetworkReply* reply) { const QString DATA_OBJECT_PLACE_KEY = "place"; const QString DATA_OBJECT_USER_LOCATION_KEY = "location"; @@ -461,7 +460,7 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject, const emit possibleDomainChangeRequiredViaICEForID(iceServerAddress, domainID); } - LookupTrigger trigger = (LookupTrigger) reply.property(LOOKUP_TRIGGER_KEY).toInt(); + LookupTrigger trigger = (LookupTrigger) reply->property(LOOKUP_TRIGGER_KEY).toInt(); // set our current root place id to the ID that came back @@ -495,7 +494,7 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject, const } // check if we had a path to override the path returned - QString overridePath = reply.property(OVERRIDE_PATH_KEY).toString(); + QString overridePath = reply->property(OVERRIDE_PATH_KEY).toString(); if (!overridePath.isEmpty() && overridePath != "/") { // make sure we don't re-handle an overriden path if this was a refresh of info from API @@ -543,10 +542,10 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject, const } } -void AddressManager::handleAPIError(QNetworkReply& errorReply) { - qCDebug(networking) << "AddressManager API error -" << errorReply.error() << "-" << errorReply.errorString(); +void AddressManager::handleAPIError(QNetworkReply* errorReply) { + qCDebug(networking) << "AddressManager API error -" << errorReply->error() << "-" << errorReply->errorString(); - if (errorReply.error() == QNetworkReply::ContentNotFoundError) { + if (errorReply->error() == QNetworkReply::ContentNotFoundError) { // if this is a lookup that has no result, don't keep re-trying it _previousLookup.clear(); @@ -874,14 +873,14 @@ QString AddressManager::getDomainID() const { return DependencyManager::get()->getDomainHandler().getUUID().toString(); } -void AddressManager::handleShareableNameAPIResponse(QNetworkReply& requestReply) { +void AddressManager::handleShareableNameAPIResponse(QNetworkReply* requestReply) { // make sure that this response is for the domain we're currently connected to auto domainID = DependencyManager::get()->getDomainHandler().getUUID(); - if (requestReply.url().toString().contains(uuidStringWithoutCurlyBraces(domainID))) { + if (requestReply->url().toString().contains(uuidStringWithoutCurlyBraces(domainID))) { // check for a name or default name in the API response - QJsonObject responseObject = QJsonDocument::fromJson(requestReply.readAll()).object(); + QJsonObject responseObject = QJsonDocument::fromJson(requestReply->readAll()).object(); QJsonObject domainObject = responseObject["domain"].toObject(); const QString DOMAIN_NAME_KEY = "name"; @@ -917,7 +916,7 @@ void AddressManager::lookupShareableNameForDomainID(const QUuid& domainID) { // no error callback handling // in the case of an error we simply assume there is no default place name - callbackParams.jsonCallbackReceiver = this; + callbackParams.callbackReceiver = this; callbackParams.jsonCallbackMethod = "handleShareableNameAPIResponse"; DependencyManager::get()->sendRequest(GET_DOMAIN_ID.arg(uuidStringWithoutCurlyBraces(domainID)), diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index 38eb7ee670..37b85a9acd 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -417,13 +417,13 @@ signals: void goForwardPossible(bool isPossible); private slots: - void handleAPIResponse(QNetworkReply& requestReply); - void handleAPIError(QNetworkReply& errorReply); + void handleAPIResponse(QNetworkReply* requestReply); + void handleAPIError(QNetworkReply* errorReply); - void handleShareableNameAPIResponse(QNetworkReply& requestReply); + void handleShareableNameAPIResponse(QNetworkReply* requestReply); private: - void goToAddressFromObject(const QVariantMap& addressMap, const QNetworkReply& reply); + void goToAddressFromObject(const QVariantMap& addressMap, const QNetworkReply* reply); // Set host and port, and return `true` if it was changed. bool setHost(const QString& host, LookupTrigger trigger, quint16 port = 0); diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 4920ea97c7..c5c49f68fe 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -549,7 +549,7 @@ void NodeList::handleICEConnectionToDomainServer() { _domainHandler.getICEClientID(), _domainHandler.getPendingDomainID()); } -} +} void NodeList::pingPunchForDomainServer() { // make sure if we're here that we actually still need to ping the domain-server diff --git a/libraries/networking/src/UserActivityLogger.cpp b/libraries/networking/src/UserActivityLogger.cpp index 7a92d4bad9..a5ee417939 100644 --- a/libraries/networking/src/UserActivityLogger.cpp +++ b/libraries/networking/src/UserActivityLogger.cpp @@ -65,7 +65,7 @@ void UserActivityLogger::logAction(QString action, QJsonObject details, JSONCall // if no callbacks specified, call our owns if (params.isEmpty()) { - params.errorCallbackReceiver = this; + params.callbackReceiver = this; params.errorCallbackMethod = "requestError"; } @@ -75,8 +75,8 @@ void UserActivityLogger::logAction(QString action, QJsonObject details, JSONCall params, NULL, multipart); } -void UserActivityLogger::requestError(QNetworkReply& errorReply) { - qCDebug(networking) << errorReply.error() << "-" << errorReply.errorString(); +void UserActivityLogger::requestError(QNetworkReply* errorReply) { + qCDebug(networking) << errorReply->error() << "-" << errorReply->errorString(); } void UserActivityLogger::launch(QString applicationVersion, bool previousSessionCrashed, int previousSessionRuntime) { diff --git a/libraries/networking/src/UserActivityLogger.h b/libraries/networking/src/UserActivityLogger.h index b44c60eba7..e4b91b1e81 100644 --- a/libraries/networking/src/UserActivityLogger.h +++ b/libraries/networking/src/UserActivityLogger.h @@ -50,7 +50,7 @@ public slots: void wentTo(AddressManager::LookupTrigger trigger, QString destinationType, QString destinationName); private slots: - void requestError(QNetworkReply& errorReply); + void requestError(QNetworkReply* errorReply); private: UserActivityLogger(); diff --git a/libraries/qml/src/qml/OffscreenSurface.cpp b/libraries/qml/src/qml/OffscreenSurface.cpp index 688f3fdb5f..f0c3dfdffd 100644 --- a/libraries/qml/src/qml/OffscreenSurface.cpp +++ b/libraries/qml/src/qml/OffscreenSurface.cpp @@ -286,6 +286,13 @@ void OffscreenSurface::loadInternal(const QUrl& qmlSource, if (QThread::currentThread() != thread()) { qFatal("Called load on a non-surface thread"); } + + // For desktop toolbar mode window: stop script when window is closed. + if (qmlSource.isEmpty()) { + getSurfaceContext()->engine()->quit(); + return; + } + // Synchronous loading may take a while; restart the deadlock timer QMetaObject::invokeMethod(qApp, "updateHeartbeat", Qt::DirectConnection); diff --git a/libraries/script-engine/src/AudioScriptingInterface.cpp b/libraries/script-engine/src/AudioScriptingInterface.cpp index f248c20d41..be419e8005 100644 --- a/libraries/script-engine/src/AudioScriptingInterface.cpp +++ b/libraries/script-engine/src/AudioScriptingInterface.cpp @@ -23,6 +23,21 @@ void registerAudioMetaTypes(QScriptEngine* engine) { qScriptRegisterMetaType(engine, soundSharedPointerToScriptValue, soundSharedPointerFromScriptValue); } + +void AudioScriptingInterface::setLocalAudioInterface(AbstractAudioInterface* audioInterface) { + if (_localAudioInterface) { + disconnect(_localAudioInterface, &AbstractAudioInterface::isStereoInputChanged, + this, &AudioScriptingInterface::isStereoInputChanged); + } + + _localAudioInterface = audioInterface; + + if (_localAudioInterface) { + connect(_localAudioInterface, &AbstractAudioInterface::isStereoInputChanged, + this, &AudioScriptingInterface::isStereoInputChanged); + } +} + ScriptAudioInjector* AudioScriptingInterface::playSystemSound(SharedSoundPointer sound, const QVector3D& position) { AudioInjectorOptions options; options.position = glm::vec3(position.x(), position.y(), position.z()); @@ -61,11 +76,10 @@ ScriptAudioInjector* AudioScriptingInterface::playSound(SharedSoundPointer sound } bool AudioScriptingInterface::setStereoInput(bool stereo) { - bool stereoInputChanged = false; if (_localAudioInterface) { - stereoInputChanged = _localAudioInterface->setIsStereoInput(stereo); + QMetaObject::invokeMethod(_localAudioInterface, "setIsStereoInput", Q_ARG(bool, stereo)); } - return stereoInputChanged; + return true; } bool AudioScriptingInterface::isStereoInput() { diff --git a/libraries/script-engine/src/AudioScriptingInterface.h b/libraries/script-engine/src/AudioScriptingInterface.h index 36fe29243d..843fa3e8f0 100644 --- a/libraries/script-engine/src/AudioScriptingInterface.h +++ b/libraries/script-engine/src/AudioScriptingInterface.h @@ -23,9 +23,11 @@ class AudioScriptingInterface : public QObject, public Dependency { Q_OBJECT SINGLETON_DEPENDENCY + Q_PROPERTY(bool isStereoInput READ isStereoInput WRITE setStereoInput NOTIFY isStereoInputChanged) + public: virtual ~AudioScriptingInterface() {} - void setLocalAudioInterface(AbstractAudioInterface* audioInterface) { _localAudioInterface = audioInterface; } + void setLocalAudioInterface(AbstractAudioInterface* audioInterface); protected: AudioScriptingInterface() {} @@ -52,7 +54,7 @@ protected: /**jsdoc * @function Audio.setStereoInput * @param {boolean} stereo - * @returns {boolean} + * @returns {boolean} */ Q_INVOKABLE bool setStereoInput(bool stereo); @@ -114,6 +116,13 @@ signals: */ void inputReceived(const QByteArray& inputSamples); + /**jsdoc + * @function Audio.isStereoInputChanged + * @param {boolean} isStereo + * @returns {Signal} + */ + void isStereoInputChanged(bool isStereo); + private: AbstractAudioInterface* _localAudioInterface { nullptr }; }; diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index f8c99b192f..99c02ba1f6 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -1639,22 +1639,24 @@ QVariantMap ScriptEngine::fetchModuleSource(const QString& modulePath, const boo loader->start(MAX_RETRIES); if (!loader->isFinished()) { - QTimer monitor; - QEventLoop loop; - QObject::connect(loader, &BatchLoader::finished, this, [&monitor, &loop]{ - monitor.stop(); - loop.quit(); + // This lambda can get called AFTER this local scope has completed. + // This is why we pass smart ptrs to the lambda instead of references to local variables. + auto monitor = std::make_shared(); + auto loop = std::make_shared(); + QObject::connect(loader, &BatchLoader::finished, this, [monitor, loop] { + monitor->stop(); + loop->quit(); }); // this helps detect the case where stop() is invoked during the download // but not seen in time to abort processing in onload()... - connect(&monitor, &QTimer::timeout, this, [this, &loop]{ + connect(monitor.get(), &QTimer::timeout, this, [this, loop] { if (isStopping()) { - loop.exit(-1); + loop->exit(-1); } }); - monitor.start(500); - loop.exec(); + monitor->start(500); + loop->exec(); } loader->deleteLater(); return req; diff --git a/libraries/shared/src/SpatiallyNestable.cpp b/libraries/shared/src/SpatiallyNestable.cpp index 324cee3417..ccb275ffc9 100644 --- a/libraries/shared/src/SpatiallyNestable.cpp +++ b/libraries/shared/src/SpatiallyNestable.cpp @@ -165,6 +165,10 @@ void SpatiallyNestable::forgetChild(SpatiallyNestablePointer newChild) const { void SpatiallyNestable::setParentJointIndex(quint16 parentJointIndex) { _parentJointIndex = parentJointIndex; + auto parent = _parent.lock(); + if (parent) { + parent->recalculateChildCauterization(); + } } glm::vec3 SpatiallyNestable::worldToLocal(const glm::vec3& position, diff --git a/libraries/shared/src/SpatiallyNestable.h b/libraries/shared/src/SpatiallyNestable.h index 5d4793ba4e..361f0aaf17 100644 --- a/libraries/shared/src/SpatiallyNestable.h +++ b/libraries/shared/src/SpatiallyNestable.h @@ -218,6 +218,7 @@ protected: virtual void beParentOfChild(SpatiallyNestablePointer newChild) const; virtual void forgetChild(SpatiallyNestablePointer newChild) const; + virtual void recalculateChildCauterization() const { } mutable ReadWriteLockable _childrenLock; mutable QHash _children; diff --git a/libraries/shared/src/shared/FileLogger.cpp b/libraries/shared/src/shared/FileLogger.cpp index 6a10629ee5..b64d08c0d8 100644 --- a/libraries/shared/src/shared/FileLogger.cpp +++ b/libraries/shared/src/shared/FileLogger.cpp @@ -30,7 +30,7 @@ signals: void rollingLogFile(QString newFilename); protected: - void rollFileIfNecessary(QFile& file, bool notifyListenersIfRolled = true); + void rollFileIfNecessary(QFile& file, bool force = false, bool notifyListenersIfRolled = true); virtual bool processQueueItems(const Queue& messages) override; private: @@ -79,12 +79,12 @@ FilePersistThread::FilePersistThread(const FileLogger& logger) : _logger(logger) // A file may exist from a previous run - if it does, roll the file and suppress notifying listeners. QFile file(_logger._fileName); if (file.exists()) { - rollFileIfNecessary(file, false); + rollFileIfNecessary(file, true, false); } } -void FilePersistThread::rollFileIfNecessary(QFile& file, bool notifyListenersIfRolled) { - if (file.size() > MAX_LOG_SIZE) { +void FilePersistThread::rollFileIfNecessary(QFile& file, bool force, bool notifyListenersIfRolled) { + if (force || (file.size() > MAX_LOG_SIZE)) { QString newFileName = getLogRollerFilename(); if (file.copy(newFileName)) { file.open(QIODevice::WriteOnly | QIODevice::Truncate); diff --git a/libraries/ui/src/Tooltip.cpp b/libraries/ui/src/Tooltip.cpp index c0c015e72f..bd2c4e6d8f 100644 --- a/libraries/ui/src/Tooltip.cpp +++ b/libraries/ui/src/Tooltip.cpp @@ -83,7 +83,7 @@ void Tooltip::requestHyperlinkImage() { auto accountManager = DependencyManager::get(); JSONCallbackParameters callbackParams; - callbackParams.jsonCallbackReceiver = this; + callbackParams.callbackReceiver = this; callbackParams.jsonCallbackMethod = "handleAPIResponse"; accountManager->sendRequest(GET_PLACE.arg(_title), @@ -94,9 +94,9 @@ void Tooltip::requestHyperlinkImage() { } } -void Tooltip::handleAPIResponse(QNetworkReply& requestReply) { +void Tooltip::handleAPIResponse(QNetworkReply* requestReply) { // did a preview image come back? - QJsonObject responseObject = QJsonDocument::fromJson(requestReply.readAll()).object(); + QJsonObject responseObject = QJsonDocument::fromJson(requestReply->readAll()).object(); QJsonObject dataObject = responseObject["data"].toObject(); const QString PLACE_KEY = "place"; diff --git a/libraries/ui/src/Tooltip.h b/libraries/ui/src/Tooltip.h index 5e884a7aea..b1bf7b7f3e 100644 --- a/libraries/ui/src/Tooltip.h +++ b/libraries/ui/src/Tooltip.h @@ -49,7 +49,7 @@ signals: void imageURLChanged(); private slots: - void handleAPIResponse(QNetworkReply& requestReply); + void handleAPIResponse(QNetworkReply* requestReply); private: void requestHyperlinkImage(); diff --git a/libraries/ui/src/ui/TabletScriptingInterface.cpp b/libraries/ui/src/ui/TabletScriptingInterface.cpp index 2c52e669a0..6f00e046af 100644 --- a/libraries/ui/src/ui/TabletScriptingInterface.cpp +++ b/libraries/ui/src/ui/TabletScriptingInterface.cpp @@ -648,6 +648,26 @@ void TabletProxy::loadQMLSource(const QVariant& path, bool resizable) { } } +void TabletProxy::stopQMLSource() { + // For desktop toolbar mode dialogs. + if (!_toolbarMode || !_desktopWindow) { + qCDebug(uiLogging) << "tablet cannot clear QML because not desktop toolbar mode"; + return; + } + + auto root = _desktopWindow->asQuickItem(); + if (root) { + QMetaObject::invokeMethod(root, "loadSource", Q_ARG(const QVariant&, "")); + if (!_currentPathLoaded.toString().isEmpty()) { + emit screenChanged(QVariant("QML"), ""); + } + _currentPathLoaded = ""; + _state = State::Home; + } else { + qCDebug(uiLogging) << "tablet cannot clear QML because _desktopWindow is null"; + } +} + bool TabletProxy::pushOntoStack(const QVariant& path) { if (QThread::currentThread() != thread()) { bool result = false; @@ -719,6 +739,7 @@ void TabletProxy::loadHomeScreen(bool forceOntoHomeScreen) { // close desktop window if (_desktopWindow->asQuickItem()) { QMetaObject::invokeMethod(_desktopWindow->asQuickItem(), "setShown", Q_ARG(const QVariant&, QVariant(false))); + stopQMLSource(); // Stop the currently loaded QML running. } } _state = State::Home; diff --git a/libraries/ui/src/ui/TabletScriptingInterface.h b/libraries/ui/src/ui/TabletScriptingInterface.h index 1ab29ca3fd..2d37402d01 100644 --- a/libraries/ui/src/ui/TabletScriptingInterface.h +++ b/libraries/ui/src/ui/TabletScriptingInterface.h @@ -443,6 +443,9 @@ protected: bool _showRunningScripts { false }; TabletButtonListModel _buttons; + +private: + void stopQMLSource(); }; Q_DECLARE_METATYPE(TabletProxy*); diff --git a/scripts/system/assets/animations/Cheer.fbx b/scripts/system/assets/animations/Cheering.fbx similarity index 100% rename from scripts/system/assets/animations/Cheer.fbx rename to scripts/system/assets/animations/Cheering.fbx diff --git a/scripts/system/assets/animations/Clap.fbx b/scripts/system/assets/animations/Clapping.fbx similarity index 100% rename from scripts/system/assets/animations/Clap.fbx rename to scripts/system/assets/animations/Clapping.fbx diff --git a/scripts/system/assets/animations/Cry.fbx b/scripts/system/assets/animations/Crying.fbx similarity index 67% rename from scripts/system/assets/animations/Cry.fbx rename to scripts/system/assets/animations/Crying.fbx index 7ecd6415a5..2e60ba2450 100644 Binary files a/scripts/system/assets/animations/Cry.fbx and b/scripts/system/assets/animations/Crying.fbx differ diff --git a/scripts/system/assets/animations/Dance.fbx b/scripts/system/assets/animations/Dancing.fbx similarity index 100% rename from scripts/system/assets/animations/Dance.fbx rename to scripts/system/assets/animations/Dancing.fbx diff --git a/scripts/system/assets/animations/Point.fbx b/scripts/system/assets/animations/Pointing.fbx similarity index 100% rename from scripts/system/assets/animations/Point.fbx rename to scripts/system/assets/animations/Pointing.fbx diff --git a/scripts/system/assets/animations/Wave.fbx b/scripts/system/assets/animations/Waving.fbx similarity index 100% rename from scripts/system/assets/animations/Wave.fbx rename to scripts/system/assets/animations/Waving.fbx diff --git a/scripts/system/assets/models/teleport-destination.fbm/Teleportation-Destination-Texture2.png b/scripts/system/assets/models/teleport-destination.fbm/Teleportation-Destination-Texture2.png new file mode 100644 index 0000000000..eb9addcfca Binary files /dev/null and b/scripts/system/assets/models/teleport-destination.fbm/Teleportation-Destination-Texture2.png differ diff --git a/scripts/system/controllers/grab.js b/scripts/system/controllers/grab.js index ba973f0108..066ef18c97 100644 --- a/scripts/system/controllers/grab.js +++ b/scripts/system/controllers/grab.js @@ -315,7 +315,7 @@ Grabber.prototype.pressEvent = function(event) { return; } - if (event.isLeftButton !== true || event.isRightButton === true || event.isMiddleButton === true) { + if (event.button !== "LEFT") { return; } @@ -419,7 +419,7 @@ Grabber.prototype.pressEvent = function(event) { }; Grabber.prototype.releaseEvent = function(event) { - if ((event.isLeftButton!==true || event.isRightButton===true || event.isMiddleButton===true) && !HMD.active) { + if (event.button !== "LEFT" && !HMD.active) { return; } diff --git a/scripts/system/emote.js b/scripts/system/emote.js index 87fc86d569..b99972253f 100644 --- a/scripts/system/emote.js +++ b/scripts/system/emote.js @@ -16,7 +16,8 @@ (function() { // BEGIN LOCAL_SCOPE -var EMOTE_ANIMATIONS = ['Cry', 'Surprised', 'Dance', 'Cheer', 'Wave', 'Fall', 'Point', 'Clap', 'Sit1', 'Sit2', 'Sit3', 'Love']; +var EMOTE_ANIMATIONS = + ['Crying', 'Surprised', 'Dancing', 'Cheering', 'Waving', 'Fall', 'Pointing', 'Clapping', 'Sit1', 'Sit2', 'Sit3', 'Love']; var ANIMATIONS = Array(); var eventMappingName = "io.highfidelity.away"; // restoreAnimation on hand controller button events, too @@ -36,6 +37,7 @@ var EMOTE_LABEL = "EMOTE"; var EMOTE_APP_SORT_ORDER = 12; var FPS = 60; var MSEC_PER_SEC = 1000; +var FINISHED = 3; // see ScriptableResource::State var onEmoteScreen = false; var button; @@ -73,63 +75,65 @@ function onWebEventReceived(event) { if (event.type === "click") { + // Allow for a random sitting animation when a user selects sit + var randSit = Math.floor(Math.random() * 3) + 1; + var emoteName = event.data; - if (activeTimer !== false) { - Script.clearTimeout(activeTimer); + if (emoteName === "Sit"){ + emoteName = event.data + randSit; // Sit1, Sit2, Sit3 } - // If the activeEmote is different from the chosen emote, then play the new emote. Other wise, - // This is a second click on the same emote as the activeEmote, and we will just stop it. - if (activeEmote !== emoteName) { - activeEmote = emoteName; + if (ANIMATIONS[emoteName].resource.state === FINISHED) { - // Allow for a random sitting animation when a user selects sit - var randSit = Math.floor(Math.random() * 3) + 1; - if (emoteName === "Sit"){ - emoteName = event.data + randSit; // "Sit1, Sit2, Sit3" + if (activeTimer !== false) { + Script.clearTimeout(activeTimer); } - var frameCount = ANIMATIONS[emoteName].animation.frames.length; - - // Three types of emotes (non-looping end, non-looping return, looping) - if (emoteName.match(/^Sit.*$/) || emoteName === "Fall") { // non-looping end - - MyAvatar.overrideAnimation(ANIMATIONS[emoteName].url, FPS, false, 0, frameCount); - - // Non-looping return - } else if (emoteName === "Love" || emoteName === "Surprised" || emoteName === "Cry" || emoteName === "Point"){ - - MyAvatar.overrideAnimation(ANIMATIONS[emoteName].url, FPS, false, 0, frameCount); - var timeOut = MSEC_PER_SEC * frameCount / FPS; - activeTimer = Script.setTimeout(function () { - MyAvatar.restoreAnimation(); - activeTimer = false; - activeEmote = false; - }, timeOut); + // If the activeEmote is different from the chosen emote, then play the new emote + // This is a second click on the same emote as the activeEmote, and we will just stop it + if (activeEmote !== emoteName) { + activeEmote = emoteName; - } else { // Looping - - MyAvatar.overrideAnimation(ANIMATIONS[emoteName].url, FPS, true, 0, frameCount); + + // Sit is the only animation currently that plays and then ends at the last frame + if (emoteName.match(/^Sit.*$/)) { - } - - } else { - activeEmote = false; - MyAvatar.restoreAnimation(); - } + // If user provides input during a sit, the avatar animation state should be restored + Controller.keyPressEvent.connect(restoreAnimation); + MyAvatar.overrideAnimation(ANIMATIONS[emoteName].url, FPS, false, 0, frameCount); + + } else { + + activeEmote = emoteName; + var frameCount = ANIMATIONS[emoteName].animation.frames.length; + MyAvatar.overrideAnimation(ANIMATIONS[emoteName].url, FPS, false, 0, frameCount); - + var timeOut = MSEC_PER_SEC * frameCount / FPS; + activeTimer = Script.setTimeout(function () { + MyAvatar.restoreAnimation(); + activeTimer = false; + activeEmote = false; + }, timeOut); + + } + + } else { + activeEmote = false; + MyAvatar.restoreAnimation(); + } + } } } -// If a user provides input, end the emote animation and restore the navigation animation states (idle, walk, run) +// Restore the navigation animation states (idle, walk, run) function restoreAnimation() { MyAvatar.restoreAnimation(); + + // Make sure the input is disconnected after animations are restored so it doesn't affect any emotes other than sit + Controller.keyPressEvent.disconnect(restoreAnimation); } - -Controller.keyPressEvent.connect(restoreAnimation); - + // Note peek() so as to not interfere with other mappings. eventMapping.from(Controller.Standard.LeftPrimaryThumb).peek().to(restoreAnimation); eventMapping.from(Controller.Standard.RightPrimaryThumb).peek().to(restoreAnimation); @@ -137,6 +141,10 @@ eventMapping.from(Controller.Standard.LeftSecondaryThumb).peek().to(restoreAnima eventMapping.from(Controller.Standard.RightSecondaryThumb).peek().to(restoreAnimation); eventMapping.from(Controller.Standard.LB).peek().to(restoreAnimation); eventMapping.from(Controller.Standard.LS).peek().to(restoreAnimation); +eventMapping.from(Controller.Standard.RY).peek().to(restoreAnimation); +eventMapping.from(Controller.Standard.RX).peek().to(restoreAnimation); +eventMapping.from(Controller.Standard.LY).peek().to(restoreAnimation); +eventMapping.from(Controller.Standard.LX).peek().to(restoreAnimation); eventMapping.from(Controller.Standard.LeftGrip).peek().to(restoreAnimation); eventMapping.from(Controller.Standard.RB).peek().to(restoreAnimation); eventMapping.from(Controller.Standard.RS).peek().to(restoreAnimation); diff --git a/scripts/system/html/EmoteApp.html b/scripts/system/html/EmoteApp.html index 16dee490a9..6b42fb8dc8 100644 --- a/scripts/system/html/EmoteApp.html +++ b/scripts/system/html/EmoteApp.html @@ -98,14 +98,14 @@

Choose an emote:

-

+

-

-

-

+

+

+

-

-

+

+

diff --git a/scripts/system/makeUserConnection.js b/scripts/system/makeUserConnection.js index d9003ffeaa..8642fc5ce6 100644 --- a/scripts/system/makeUserConnection.js +++ b/scripts/system/makeUserConnection.js @@ -88,8 +88,8 @@ "polarFinish": 1, "radiusFinish": 0.3, "radiusStart": 0.04, - "speedSpread": 0.01, - "radiusSpread": 0.9, + "speedSpread": 0.00, + "radiusSpread": 0.0, "textures": "http://hifi-content.s3.amazonaws.com/alan/dev/Particles/Bokeh-Particle.png", "color": {"red": 200, "green": 170, "blue": 255}, "colorFinish": {"red": 0, "green": 134, "blue": 255}, diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index 9b540aefc8..e265ddb621 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -17,7 +17,6 @@ var SNAPSHOT_DELAY = 500; // 500ms var FINISH_SOUND_DELAY = 350; var resetOverlays; var reticleVisible; -var clearOverlayWhenMoving; var buttonName = "SNAP"; var buttonConnected = false; @@ -286,6 +285,7 @@ function printToPolaroid(image_url) { var polaroid_url = image_url; var model_pos = Vec3.sum(MyAvatar.position, Vec3.multiply(1.25, Quat.getForward(MyAvatar.orientation))); + model_pos.y += 0.2; // Print a bit closer to the head var model_q1 = MyAvatar.orientation; var model_q2 = Quat.angleAxis(90, Quat.getRight(model_q1)); @@ -295,11 +295,11 @@ function printToPolaroid(image_url) { "type": 'Model', "shapeType": 'box', - "name": "New Snapshot", - "description": "Printed from Snaps", + "name": "Snapshot by " + MyAvatar.sessionDisplayName, + "description": "Printed from SNAP app", "modelURL": POLAROID_MODEL_URL, - "dimensions": { "x": 0.5667, "y": 0.0212, "z": 0.4176 }, + "dimensions": { "x": 0.5667, "y": 0.042, "z": 0.4176 }, "position": model_pos, "rotation": model_rot, @@ -307,9 +307,9 @@ function printToPolaroid(image_url) { "density": 200, "restitution": 0.15, - "gravity": { "x": 0, "y": -4.5, "z": 0 }, + "gravity": { "x": 0, "y": -2.5, "z": 0 }, - "velocity": { "x": 0, "y": 3.5, "z": 0 }, + "velocity": { "x": 0, "y": 1.95, "z": 0 }, "angularVelocity": { "x": -1.0, "y": 0, "z": -1.3 }, "dynamic": true, @@ -438,11 +438,6 @@ function takeSnapshot() { isUploadingPrintableStill = true; updatePrintPermissions(); - // Raising the desktop for the share dialog at end will interact badly with clearOverlayWhenMoving. - // Turn it off now, before we start futzing with things (and possibly moving). - clearOverlayWhenMoving = MyAvatar.getClearOverlayWhenMoving(); // Do not use Settings. MyAvatar keeps a separate copy. - MyAvatar.setClearOverlayWhenMoving(false); - // We will record snapshots based on the starting location. That could change, e.g., when recording a .gif. // Even the domainID could change (e.g., if the user falls into a teleporter while recording). href = location.href; @@ -544,9 +539,6 @@ function stillSnapshotTaken(pathStillSnapshot, notify) { // last element in data array tells dialog whether we can share or not Settings.setValue("previousStillSnapPath", pathStillSnapshot); - if (clearOverlayWhenMoving) { - MyAvatar.setClearOverlayWhenMoving(true); // not until after the share dialog - } HMD.openTablet(); isDomainOpen(domainID, function (canShare) { @@ -590,9 +582,6 @@ function processingGifStarted(pathStillSnapshot) { } Settings.setValue("previousStillSnapPath", pathStillSnapshot); - if (clearOverlayWhenMoving) { - MyAvatar.setClearOverlayWhenMoving(true); // not until after the share dialog - } HMD.openTablet(); isDomainOpen(domainID, function (canShare) {