mirror of
https://github.com/overte-org/overte.git
synced 2025-04-22 14:33:34 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi
This commit is contained in:
commit
d2dda64dad
70 changed files with 590 additions and 524 deletions
android/app/src/main/cpp
assignment-client/src/entities
domain-server/src
DomainGatekeeper.cppDomainGatekeeper.hDomainServer.cppDomainServer.hDomainServerSettingsManager.cppDomainServerSettingsManager.h
interface
resources/qml/hifi
src
libraries
audio-client/src
audio/src
avatars-renderer/src/avatars-renderer
fbx/src
networking/src
AccountManager.cppAccountManager.hAddressManager.cppAddressManager.hNodeList.cppUserActivityLogger.cppUserActivityLogger.h
qml/src/qml
script-engine/src
shared/src
ui/src
scripts/system
assets
animations
models/teleport-destination.fbm
controllers
emote.jshtml
makeUserConnection.jssnapshot.js
|
@ -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<AccountManager>();
|
||||
|
||||
__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<AccountManager>()->isLoggedIn();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_io_highfidelity_hifiinterface_MainActivity_nativeLogout(JNIEnv *env, jobject instance) {
|
||||
AndroidHelper::instance().getAccountManager()->logout();
|
||||
DependencyManager::get<AccountManager>()->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<AccountManager>()->getAccountInfo().getUsername();
|
||||
return env->NewStringUTF(username.toLatin1().data());
|
||||
}
|
||||
|
||||
|
|
|
@ -504,6 +504,11 @@ void EntityServer::startDynamicDomainVerification() {
|
|||
QString thisDomainID = DependencyManager::get<AddressManager>()->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;
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -51,14 +51,14 @@ public slots:
|
|||
void processICEPingReplyPacket(QSharedPointer<ReceivedMessage> message);
|
||||
void processICEPeerInformationPacket(QSharedPointer<ReceivedMessage> 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();
|
||||
|
||||
|
|
|
@ -514,13 +514,13 @@ void DomainServer::getTemporaryName(bool force) {
|
|||
|
||||
// request a temporary name from the metaverse
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
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<AccountManager>()->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()));
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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<ReceivedMessage> message);
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -32,6 +32,6 @@ StackView {
|
|||
TabletPreferencesDialog {
|
||||
id: root
|
||||
objectName: "TabletGeneralPreferences"
|
||||
showCategories: ["User Interface", "HMD", "Snapshots", "Privacy"]
|
||||
showCategories: ["User Interface", "Mouse Sensitivity", "HMD", "Snapshots", "Privacy"]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,31 +10,11 @@
|
|||
//
|
||||
#include "AndroidHelper.h"
|
||||
#include <QDebug>
|
||||
#include <AccountManager.h>
|
||||
|
||||
AndroidHelper::AndroidHelper() {
|
||||
}
|
||||
|
||||
AndroidHelper::~AndroidHelper() {
|
||||
workerThread.quit();
|
||||
workerThread.wait();
|
||||
}
|
||||
|
||||
void AndroidHelper::init() {
|
||||
workerThread.start();
|
||||
_accountManager = QSharedPointer<AccountManager>(new AccountManager, &QObject::deleteLater);
|
||||
_accountManager->setIsAgent(true);
|
||||
_accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL());
|
||||
_accountManager->setSessionID(DependencyManager::get<AccountManager>()->getSessionID());
|
||||
connect(_accountManager.data(), &AccountManager::loginComplete, [](const QUrl& authURL) {
|
||||
DependencyManager::get<AccountManager>()->setAccountInfo(AndroidHelper::instance().getAccountManager()->getAccountInfo());
|
||||
DependencyManager::get<AccountManager>()->setAuthURL(authURL);
|
||||
});
|
||||
|
||||
connect(_accountManager.data(), &AccountManager::logoutComplete, [] () {
|
||||
DependencyManager::get<AccountManager>()->logout();
|
||||
});
|
||||
_accountManager->moveToThread(&workerThread);
|
||||
}
|
||||
|
||||
void AndroidHelper::requestActivity(const QString &activityName, const bool backToScene) {
|
||||
|
|
|
@ -13,8 +13,6 @@
|
|||
#define hifi_Android_Helper_h
|
||||
|
||||
#include <QObject>
|
||||
#include <QThread>
|
||||
#include <AccountManager.h>
|
||||
|
||||
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<AccountManager> getAccountManager() { return _accountManager; }
|
||||
AndroidHelper(AndroidHelper const&) = delete;
|
||||
void operator=(AndroidHelper const&) = delete;
|
||||
|
||||
|
@ -49,8 +45,6 @@ signals:
|
|||
private:
|
||||
AndroidHelper();
|
||||
~AndroidHelper();
|
||||
QSharedPointer<AccountManager> _accountManager;
|
||||
QThread workerThread;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1081,6 +1081,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
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>();
|
||||
addressManager->moveToThread(nodeList->thread());
|
||||
|
||||
const char** constArgv = const_cast<const char**>(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<AddressManager>();
|
||||
|
||||
// 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();
|
||||
|
|
|
@ -97,7 +97,7 @@ void DiscoverabilityManager::updateLocation() {
|
|||
locationObject.insert(AVAILABILITY_KEY_IN_LOCATION, findableByString(static_cast<Discoverability::Mode>(_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()) {
|
||||
|
|
|
@ -51,7 +51,7 @@ public:
|
|||
static QString findableByString(Discoverability::Mode discoverabilityMode);
|
||||
|
||||
private slots:
|
||||
void handleHeartbeatResponse(QNetworkReply& requestReply);
|
||||
void handleHeartbeatResponse(QNetworkReply* requestReply);
|
||||
|
||||
private:
|
||||
DiscoverabilityManager();
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -36,13 +36,13 @@
|
|||
#include <SettingHandle.h>
|
||||
#include <UsersScriptingInterface.h>
|
||||
#include <UUID.h>
|
||||
#include <avatars-renderer/OtherAvatar.h>
|
||||
#include <shared/ConicalViewFrustum.h>
|
||||
|
||||
#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<Avatar>(sortData.getAvatar());
|
||||
const auto otherAvatar = std::static_pointer_cast<OtherAvatar>(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<NodeList>()->isPersonalMutingNode(avatar->getID());
|
||||
if (ignoring) {
|
||||
|
|
|
@ -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<EntityItem>(object);
|
||||
entity->setCauterized(!_prevShouldDrawHead);
|
||||
entity->setCauterized(cauterize);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -545,17 +549,42 @@ void MyAvatar::simulate(float deltaTime) {
|
|||
animateScaleChanges(deltaTime);
|
||||
|
||||
if (_cauterizationNeedsUpdate) {
|
||||
const std::unordered_set<int>& 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();
|
||||
|
|
|
@ -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<float, MAX_DRIVE_KEYS> _driveKeys;
|
||||
std::bitset<MAX_DRIVE_KEYS> _disabledDriveKeys;
|
||||
|
||||
bool _enableFlying { true };
|
||||
bool _enableFlying { false };
|
||||
bool _wasPushing { false };
|
||||
bool _isPushing { false };
|
||||
bool _isBeingPushed { false };
|
||||
|
@ -1495,7 +1486,6 @@ private:
|
|||
ThreadSafeValueCache<QUrl> _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<int> _headBoneSet;
|
||||
std::unordered_set<SpatiallyNestablePointer> _cauterizedChildrenOfHead;
|
||||
bool _prevShouldDrawHead;
|
||||
bool _rigEnabled { true };
|
||||
|
||||
|
@ -1621,7 +1612,7 @@ private:
|
|||
// height of user in sensor space, when standing erect.
|
||||
ThreadSafeValueCache<float> _userHeight { DEFAULT_AVATAR_HEIGHT };
|
||||
|
||||
void updateChildCauterization(SpatiallyNestablePointer object);
|
||||
void updateChildCauterization(SpatiallyNestablePointer object, bool cauterize);
|
||||
|
||||
// max unscaled forward movement speed
|
||||
ThreadSafeValueCache<float> _walkSpeed { DEFAULT_AVATAR_MAX_WALKING_SPEED };
|
||||
|
|
60
interface/src/avatar/OtherAvatar.cpp
Normal file
60
interface/src/avatar/OtherAvatar.cpp
Normal file
|
@ -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<SkeletonModel>(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<Sphere3DOverlay>();
|
||||
_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);
|
||||
}
|
||||
}
|
32
interface/src/avatar/OtherAvatar.h
Normal file
32
interface/src/avatar/OtherAvatar.h
Normal file
|
@ -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 <avatars-renderer/Avatar.h>
|
||||
#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<Sphere3DOverlay> _otherAvatarOrbMeshPlaceholder { nullptr };
|
||||
OverlayID _otherAvatarOrbMeshPlaceholderID { UNKNOWN_OVERLAY_ID };
|
||||
};
|
||||
|
||||
#endif // hifi_OtherAvatar_h
|
|
@ -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<AccountManager>();
|
||||
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<Wallet>();
|
||||
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<Wallet>();
|
||||
auto walletScriptingInterface = DependencyManager::get<WalletScriptingInterface>();
|
||||
|
@ -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<Wallet>();
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
|
||||
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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -35,5 +35,8 @@ QVariant SettingsScriptingInterface::getValue(const QString& setting, const QVar
|
|||
}
|
||||
|
||||
void SettingsScriptingInterface::setValue(const QString& setting, const QVariant& value) {
|
||||
Setting::Handle<QVariant>(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<QVariant>(deepCopy).set(value);
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(); };
|
||||
|
|
|
@ -493,7 +493,7 @@ void Snapshot::uploadSnapshot(const QString& filename, const QUrl& href) {
|
|||
multiPart->append(imagePart);
|
||||
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
JSONCallbackParameters callbackParams(uploader, "uploadSuccess", uploader, "uploadFailure");
|
||||
JSONCallbackParameters callbackParams(uploader, "uploadSuccess", "uploadFailure");
|
||||
|
||||
accountManager->sendRequest(SNAPSHOT_UPLOAD_URL, AccountManagerAuth::Required, QNetworkAccessManager::PostOperation,
|
||||
callbackParams, nullptr, multiPart);
|
||||
|
|
|
@ -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<AccountManager>();
|
||||
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<WindowScriptingInterface>()->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;
|
||||
|
|
|
@ -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
|
||||
#endif // hifi_SnapshotUploader_h
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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*)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include <graphics-scripting/Forward.h>
|
||||
#include <GLMHelpers.h>
|
||||
|
||||
|
||||
#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<glm::quat> 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()); }
|
||||
|
|
|
@ -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<SkeletonModel>(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);
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <QtCore/QThreadPool>
|
||||
#include <QtNetwork/QHttpMultiPart>
|
||||
#include <QtNetwork/QNetworkRequest>
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
#include <qthread.h>
|
||||
|
||||
#include <SettingHandle.h>
|
||||
|
@ -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>("OAuthAccessToken");
|
||||
qRegisterMetaTypeStreamOperators<OAuthAccessToken>("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<QNetworkReply*>(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() {
|
||||
|
|
|
@ -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<QNetworkReply*, JSONCallbackParameters> _pendingCallbackMap;
|
||||
|
||||
DataServerAccountInfo _accountInfo;
|
||||
bool _isWaitingForTokenRefresh { false };
|
||||
|
|
|
@ -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<NodeList>()->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<NodeList>()->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<AccountManager>()->sendRequest(GET_DOMAIN_ID.arg(uuidStringWithoutCurlyBraces(domainID)),
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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 };
|
||||
};
|
||||
|
|
|
@ -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<QTimer>();
|
||||
auto loop = std::make_shared<QEventLoop>();
|
||||
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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<QUuid, SpatiallyNestableWeakPointer> _children;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -83,7 +83,7 @@ void Tooltip::requestHyperlinkImage() {
|
|||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
|
||||
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";
|
||||
|
|
|
@ -49,7 +49,7 @@ signals:
|
|||
void imageURLChanged();
|
||||
|
||||
private slots:
|
||||
void handleAPIResponse(QNetworkReply& requestReply);
|
||||
void handleAPIResponse(QNetworkReply* requestReply);
|
||||
|
||||
private:
|
||||
void requestHyperlinkImage();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -443,6 +443,9 @@ protected:
|
|||
bool _showRunningScripts { false };
|
||||
|
||||
TabletButtonListModel _buttons;
|
||||
|
||||
private:
|
||||
void stopQMLSource();
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(TabletProxy*);
|
||||
|
|
Binary file not shown.
Binary file not shown.
After ![]() (image error) Size: 144 KiB |
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -98,14 +98,14 @@
|
|||
</div>
|
||||
<div class="content">
|
||||
<p>Choose an emote:<p>
|
||||
<p><input type="button" class="emote-button white" value="Cry">
|
||||
<p><input type="button" class="emote-button white" value="Crying">
|
||||
<input type="button" class="emote-button white" value="Surprised"></p>
|
||||
<p><input type="button" class="emote-button white" value="Dance">
|
||||
<input type="button" class="emote-button white" value="Cheer"></p>
|
||||
<p><input type="button" class="emote-button white" value="Wave">
|
||||
<p><input type="button" class="emote-button white" value="Dancing">
|
||||
<input type="button" class="emote-button white" value="Cheering"></p>
|
||||
<p><input type="button" class="emote-button white" value="Waving">
|
||||
<input type="button" class="emote-button white" value="Fall"></p>
|
||||
<p><input type="button" class="emote-button white" value="Point">
|
||||
<input type="button" class="emote-button white" value="Clap"></p>
|
||||
<p><input type="button" class="emote-button white" value="Pointing">
|
||||
<input type="button" class="emote-button white" value="Clapping"></p>
|
||||
<p><input type="button" class="emote-button white" value="Sit">
|
||||
<input type="button" class="emote-button white" value="Love"></p>
|
||||
</div>
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue