From c96c68440062d0d2f5357063b5ee9bf8d1d69206 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 5 Dec 2019 11:55:24 -0800 Subject: [PATCH 01/15] Initial path to fixing screenshare auth race condition --- domain-server/src/DomainServer.cpp | 16 ++++++-- domain-server/src/DomainServer.h | 4 +- .../ScreenshareScriptingInterface.cpp | 28 +++++++++++++ .../scripting/ScreenshareScriptingInterface.h | 5 +++ libraries/networking/src/AccountManager.cpp | 41 ++++++++++++++++--- libraries/networking/src/AccountManager.h | 4 +- 6 files changed, 86 insertions(+), 12 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index de41927fe2..9a8033e03c 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -3634,10 +3634,10 @@ void DomainServer::processAvatarZonePresencePacket(QSharedPointer()->hasValidAccessToken()) { static std::once_flag presenceAuthorityWarning; std::call_once(presenceAuthorityWarning, [] { @@ -3649,6 +3649,10 @@ void DomainServer::screensharePresence(QString roomname, QString username, int e callbackParams.callbackReceiver = this; callbackParams.jsonCallbackMethod = "handleSuccessfulScreensharePresence"; callbackParams.errorCallbackMethod = "handleFailedScreensharePresence"; + QJsonObject callbackData; + callbackData.insert("roomname", roomname); + callbackData.insert("avatarID", avatarID.toString()); + callbackParams.callbackData = callbackData; const QString PATH = "api/v1/domains/%1/screenshare"; QString domain_id = uuidStringWithoutCurlyBraces(getID()); QJsonObject json, screenshare; @@ -3666,11 +3670,17 @@ void DomainServer::screensharePresence(QString roomname, QString username, int e ); } -void DomainServer::handleSuccessfulScreensharePresence(QNetworkReply* requestReply) { +void DomainServer::handleSuccessfulScreensharePresence(QNetworkReply* requestReply, QJsonObject callbackData) { QJsonObject jsonObject = QJsonDocument::fromJson(requestReply->readAll()).object(); if (jsonObject["status"].toString() != "success") { qCWarning(domain_server) << "screensharePresence api call failed:" << QJsonDocument(jsonObject).toJson(QJsonDocument::Compact); + return; } + + auto nodeList = DependencyManager::get(); + auto packet = NLPacket::create(PacketType::AvatarZonePresence, NUM_BYTES_RFC4122_UUID, true); + packet->write(QUuid(callbackData["roomname"].toString()).toRfc4122()); + nodeList->sendPacket(std::move(packet), *(nodeList->nodeWithUUID(QUuid(callbackData["avatarID"].toString())))); } void DomainServer::handleFailedScreensharePresence(QNetworkReply* requestReply) { diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 034ccb5a18..92ef5a90b3 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -78,7 +78,7 @@ public: bool isAssetServerEnabled(); - void screensharePresence(QString roomname, QString username, int expiration_seconds = 0); + void screensharePresence(QString roomname, QString username, QUuid avatarID, int expiration_seconds = 0); public slots: /// Called by NodeList to inform us a node has been added @@ -132,7 +132,7 @@ private slots: void handleSuccessfulICEServerAddressUpdate(QNetworkReply* requestReply); void handleFailedICEServerAddressUpdate(QNetworkReply* requestReply); - void handleSuccessfulScreensharePresence(QNetworkReply* requestReply); + void handleSuccessfulScreensharePresence(QNetworkReply* requestReply, QJsonObject callbackData); void handleFailedScreensharePresence(QNetworkReply* requestReply); void updateReplicatedNodes(); diff --git a/interface/src/scripting/ScreenshareScriptingInterface.cpp b/interface/src/scripting/ScreenshareScriptingInterface.cpp index 37365c1b89..a5f7595599 100644 --- a/interface/src/scripting/ScreenshareScriptingInterface.cpp +++ b/interface/src/scripting/ScreenshareScriptingInterface.cpp @@ -37,14 +37,41 @@ ScreenshareScriptingInterface::ScreenshareScriptingInterface() { _requestScreenshareInfoRetryTimer->setSingleShot(true); _requestScreenshareInfoRetryTimer->setInterval(SCREENSHARE_INFO_REQUEST_RETRY_TIMEOUT_MS); connect(_requestScreenshareInfoRetryTimer, &QTimer::timeout, this, &ScreenshareScriptingInterface::requestScreenshareInfo); + + auto nodeList = DependencyManager::get(); + PacketReceiver& packetReceiver = nodeList->getPacketReceiver(); + packetReceiver.registerListener(PacketType::AvatarZonePresence, this, "processAvatarZonePresencePacketOnClient"); }; ScreenshareScriptingInterface::~ScreenshareScriptingInterface() { stopScreenshare(); } +void ScreenshareScriptingInterface::processAvatarZonePresencePacketOnClient(QSharedPointer message, SharedNodePointer senderNode) { + QUuid zone = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID)); + + if (zone.isNull()) { + qWarning() << "Ignoring avatar zone presence packet that doesn't specify a zone."; + return; + } + + _lastAuthorizedZoneID = zone; + + if (_waitingForAuthorization) { + requestScreenshareInfo(); + } +} + static const int MAX_NUM_SCREENSHARE_INFO_REQUEST_RETRIES = 5; void ScreenshareScriptingInterface::requestScreenshareInfo() { + if (_screenshareZoneID != _lastAuthorizedZoneID) { + qDebug() << "Client not yet authorized to screenshare. Waiting for authorization message from domain server..."; + _waitingForAuthorization = true; + return; + } + + _waitingForAuthorization = false; + _requestScreenshareInfoRetries++; if (_requestScreenshareInfoRetries >= MAX_NUM_SCREENSHARE_INFO_REQUEST_RETRIES) { @@ -174,6 +201,7 @@ void ScreenshareScriptingInterface::stopScreenshare() { _projectAPIKey = ""; _sessionID = ""; _isPresenter = false; + _waitingForAuthorization = false; } // Called when the Metaverse returns the information necessary to start/view a screen share. diff --git a/interface/src/scripting/ScreenshareScriptingInterface.h b/interface/src/scripting/ScreenshareScriptingInterface.h index 2e9cd79fcf..41e93d770d 100644 --- a/interface/src/scripting/ScreenshareScriptingInterface.h +++ b/interface/src/scripting/ScreenshareScriptingInterface.h @@ -41,6 +41,8 @@ private slots: void handleFailedScreenshareInfoGet(QNetworkReply* reply); private: + void processAvatarZonePresencePacketOnClient(QSharedPointer message, SharedNodePointer senderNode); + #if DEV_BUILD #ifdef Q_OS_WIN const QString SCREENSHARE_EXE_PATH{ PathUtils::projectRootPath() + "/screenshare/hifi-screenshare-win32-x64/hifi-screenshare.exe" }; @@ -82,6 +84,9 @@ private: QUuid _screenshareZoneID; QUuid _smartboardEntityID; bool _isPresenter{ false }; + + QUuid _lastAuthorizedZoneID; + bool _waitingForAuthorization{ false }; }; #endif // hifi_ScreenshareScriptingInterface_h diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index 5473f1a010..095dfebf5c 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -61,6 +61,18 @@ JSONCallbackParameters::JSONCallbackParameters(QObject* callbackReceiver, } +JSONCallbackParameters::JSONCallbackParameters(QObject* callbackReceiver, + const QString& jsonCallbackMethod, + const QString& errorCallbackMethod, + const QJsonObject& callbackData) : + callbackReceiver(callbackReceiver), + jsonCallbackMethod(jsonCallbackMethod), + errorCallbackMethod(errorCallbackMethod), + callbackData(callbackData) +{ + +} + QJsonObject AccountManager::dataObjectFromResponse(QNetworkReply* requestReply) { QJsonObject jsonObject = QJsonDocument::fromJson(requestReply->readAll()).object(); @@ -348,9 +360,17 @@ void AccountManager::sendRequest(const QString& path, [callbackParams, networkReply] { if (networkReply->error() == QNetworkReply::NoError) { if (!callbackParams.jsonCallbackMethod.isEmpty()) { - bool invoked = QMetaObject::invokeMethod(callbackParams.callbackReceiver, - qPrintable(callbackParams.jsonCallbackMethod), - Q_ARG(QNetworkReply*, networkReply)); + bool invoked = false; + if (callbackParams.callbackData.isEmpty()) { + invoked = QMetaObject::invokeMethod(callbackParams.callbackReceiver, + qPrintable(callbackParams.jsonCallbackMethod), + Q_ARG(QNetworkReply*, networkReply)); + } else { + invoked = QMetaObject::invokeMethod(callbackParams.callbackReceiver, + qPrintable(callbackParams.jsonCallbackMethod), + Q_ARG(QNetworkReply*, networkReply), + Q_ARG(QJsonObject, callbackParams.callbackData)); + } if (!invoked) { QString error = "Could not invoke " + callbackParams.jsonCallbackMethod + " with QNetworkReply* " @@ -366,9 +386,18 @@ void AccountManager::sendRequest(const QString& path, } } else { if (!callbackParams.errorCallbackMethod.isEmpty()) { - bool invoked = QMetaObject::invokeMethod(callbackParams.callbackReceiver, - qPrintable(callbackParams.errorCallbackMethod), - Q_ARG(QNetworkReply*, networkReply)); + bool invoked = false; + if (callbackParams.callbackData.isEmpty()) { + invoked = QMetaObject::invokeMethod(callbackParams.callbackReceiver, + qPrintable(callbackParams.errorCallbackMethod), + Q_ARG(QNetworkReply*, networkReply)); + } + else { + invoked = QMetaObject::invokeMethod(callbackParams.callbackReceiver, + qPrintable(callbackParams.errorCallbackMethod), + Q_ARG(QNetworkReply*, networkReply), + Q_ARG(QJsonObject, callbackParams.callbackData)); + } if (!invoked) { QString error = "Could not invoke " + callbackParams.errorCallbackMethod + " with QNetworkReply* " diff --git a/libraries/networking/src/AccountManager.h b/libraries/networking/src/AccountManager.h index 2e94ccf0ea..33c9190561 100644 --- a/libraries/networking/src/AccountManager.h +++ b/libraries/networking/src/AccountManager.h @@ -31,13 +31,15 @@ class JSONCallbackParameters { public: JSONCallbackParameters(QObject* callbackReceiver = nullptr, const QString& jsonCallbackMethod = QString(), - const QString& errorCallbackMethod = QString()); + const QString& errorCallbackMethod = QString(), + const QJsonObject& callbackData = QJsonObject()); bool isEmpty() const { return !callbackReceiver; } QObject* callbackReceiver; QString jsonCallbackMethod; QString errorCallbackMethod; + QJsonObject callbackData; }; namespace AccountManagerAuth { From 72342c9d3ede73f85928659bf04f6e1980ca1dd8 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 5 Dec 2019 15:48:21 -0800 Subject: [PATCH 02/15] Attempt to fix DEV-2859 with tighter constraints on screenshare resolution and framerate --- screenshare/src/screenshareApp.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/screenshare/src/screenshareApp.js b/screenshare/src/screenshareApp.js index b16f5ca993..6a33b827d4 100644 --- a/screenshare/src/screenshareApp.js +++ b/screenshare/src/screenshareApp.js @@ -223,10 +223,9 @@ function onAccessApproved(desktop_id) { mandatory: { chromeMediaSource: 'desktop', chromeMediaSourceId: desktop_id, - minWidth: 1280, maxWidth: 1280, - minHeight: 720, - maxHeight: 720 + maxHeight: 720, + maxFrameRate: 7 } } }, gotStream, handleError); @@ -261,7 +260,7 @@ function startTokboxPublisher(stream) { audioFallbackEnabled: false, audioSource: null, fitMode: 'contain', - frameRate: 30, + frameRate: 7, height: 720, insertMode: 'append', publishAudio: false, From 04fe2988f53fc8685655d3ecc77015635e4bfdea Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 5 Dec 2019 18:50:31 -0800 Subject: [PATCH 03/15] Working --- .../src/scripting/ScreenshareScriptingInterface.cpp | 3 ++- .../src/scripting/ScreenshareScriptingInterface.h | 4 ++-- libraries/networking/src/AccountManager.cpp | 10 ---------- libraries/networking/src/AccountManager.h | 6 +++--- 4 files changed, 7 insertions(+), 16 deletions(-) diff --git a/interface/src/scripting/ScreenshareScriptingInterface.cpp b/interface/src/scripting/ScreenshareScriptingInterface.cpp index a5f7595599..1e03e90482 100644 --- a/interface/src/scripting/ScreenshareScriptingInterface.cpp +++ b/interface/src/scripting/ScreenshareScriptingInterface.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include "EntityScriptingInterface.h" @@ -47,7 +48,7 @@ ScreenshareScriptingInterface::~ScreenshareScriptingInterface() { stopScreenshare(); } -void ScreenshareScriptingInterface::processAvatarZonePresencePacketOnClient(QSharedPointer message, SharedNodePointer senderNode) { +void ScreenshareScriptingInterface::processAvatarZonePresencePacketOnClient(QSharedPointer message) { QUuid zone = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID)); if (zone.isNull()) { diff --git a/interface/src/scripting/ScreenshareScriptingInterface.h b/interface/src/scripting/ScreenshareScriptingInterface.h index 41e93d770d..ec8f3cd619 100644 --- a/interface/src/scripting/ScreenshareScriptingInterface.h +++ b/interface/src/scripting/ScreenshareScriptingInterface.h @@ -18,6 +18,7 @@ #include #include +#include class ScreenshareScriptingInterface : public QObject, public Dependency { Q_OBJECT @@ -36,13 +37,12 @@ signals: void localWebEntityZOffsetChanged(const float& newZOffset); private slots: + void processAvatarZonePresencePacketOnClient(QSharedPointer message); void onWebEventReceived(const QUuid& entityID, const QVariant& message); void handleSuccessfulScreenshareInfoGet(QNetworkReply* reply); void handleFailedScreenshareInfoGet(QNetworkReply* reply); private: - void processAvatarZonePresencePacketOnClient(QSharedPointer message, SharedNodePointer senderNode); - #if DEV_BUILD #ifdef Q_OS_WIN const QString SCREENSHARE_EXE_PATH{ PathUtils::projectRootPath() + "/screenshare/hifi-screenshare-win32-x64/hifi-screenshare.exe" }; diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index 095dfebf5c..83c0fd28dd 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -51,16 +51,6 @@ const int POST_SETTINGS_INTERVAL = 10 * MSECS_PER_SECOND; const int PULL_SETTINGS_RETRY_INTERVAL = 2 * MSECS_PER_SECOND; const int MAX_PULL_RETRIES = 10; -JSONCallbackParameters::JSONCallbackParameters(QObject* callbackReceiver, - const QString& jsonCallbackMethod, - const QString& errorCallbackMethod) : - callbackReceiver(callbackReceiver), - jsonCallbackMethod(jsonCallbackMethod), - errorCallbackMethod(errorCallbackMethod) -{ - -} - JSONCallbackParameters::JSONCallbackParameters(QObject* callbackReceiver, const QString& jsonCallbackMethod, const QString& errorCallbackMethod, diff --git a/libraries/networking/src/AccountManager.h b/libraries/networking/src/AccountManager.h index 33c9190561..7dc4d0dc13 100644 --- a/libraries/networking/src/AccountManager.h +++ b/libraries/networking/src/AccountManager.h @@ -30,9 +30,9 @@ class JSONCallbackParameters { public: JSONCallbackParameters(QObject* callbackReceiver = nullptr, - const QString& jsonCallbackMethod = QString(), - const QString& errorCallbackMethod = QString(), - const QJsonObject& callbackData = QJsonObject()); + const QString& jsonCallbackMethod = QString(), + const QString& errorCallbackMethod = QString(), + const QJsonObject& callbackData = QJsonObject()); bool isEmpty() const { return !callbackReceiver; } From 3eadec3eaa17eb53d7ac56b5fd6275abe8d80e5b Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 6 Dec 2019 21:26:59 +1300 Subject: [PATCH 04/15] DriveKeys JSDoc --- interface/src/avatar/MyAvatar.h | 34 +++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index cc12e4fcee..7d313f4af7 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -436,6 +436,40 @@ class MyAvatar : public Avatar { const bool DEFAULT_STRAFE_ENABLED = true; public: + /**jsdoc + * The DriveKeys API provides constant numeric values that represent different logical keys that drive your + * avatar and camera. + * + * @namespace DriveKeys + * + * @hifi-interface + * @hifi-client-entity + * @hifi-avatar + * + * @property {number} TRANSLATE_X - Move the user's avatar in the direction of its x-axis, if the camera isn't in + * independent or mirror modes. + * @property {number} TRANSLATE_Y - Move the user's avatar in the direction of its y-axis, if the camera isn't in + * independent or mirror modes. + * @property {number} TRANSLATE_Z - Move the user's avatar in the direction of its z-axis, if the camera isn't in + * independent or mirror modes. + * @property {number} YAW - Rotate the user's avatar about its y-axis at a rate proportional to the control value, if the + * camera isn't in independent or mirror modes. + * @property {number} STEP_TRANSLATE_X - No action. + * @property {number} STEP_TRANSLATE_Y - No action. + * @property {number} STEP_TRANSLATE_Z - No action. + * @property {number} STEP_YAW - Rotate the user's avatar about its y-axis in a step increment, if the camera isn't in + * independent or mirror modes. + * @property {number} PITCH - Rotate the user's avatar head and attached camera about its negative x-axis (i.e., positive + * values pitch down) at a rate proportional to the control value, if the camera isn't in HMD, independent, or mirror + * modes. + * @property {number} ZOOM - Zoom the camera in or out. + * @property {number} DELTA_YAW - Rotate the user's avatar about its y-axis by an amount proportional to the control value, + * if the camera isn't in independent or mirror modes. + * @property {number} DELTA_PITCH - Rotate the user's avatar head and attached camera about its negative x-axis (i.e., + * positive values pitch down) by an amount proportional to the control value, if the camera isn't in HMD, independent, + * or mirror modes. + */ + /**jsdoc *

Logical keys that drive your avatar and camera.

* From afdbbb95b1671d747c10a87d9753507f33fd4826 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 6 Dec 2019 21:27:34 +1300 Subject: [PATCH 05/15] DriveKey type and update MyAvatar JSDoc --- interface/src/avatar/MyAvatar.h | 59 ++++++++++++++++----------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 7d313f4af7..d8353796b6 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -474,34 +474,34 @@ public: *

Logical keys that drive your avatar and camera.

*
* - * + * * * - * - * - * - * - * - * - * - * - * - * - * - * + * + * + * + * + * + * + * + * + * + * + * + * * *
ValueNameDescription
ValueDescription
0TRANSLATE_XMove the user's avatar in the direction of its x-axis, if the - * camera isn't in independent or mirror modes.
1TRANSLATE_YMove the user's avatar in the direction of its y-axis, if the - * camera isn't in independent or mirror modes.
2TRANSLATE_ZMove the user's avatar in the direction of its z-axis, if the - * camera isn't in independent or mirror modes
3YAWRotate the user's avatar about its y-axis at a rate proportional to the - * control value, if the camera isn't in independent or mirror modes.
4STEP_TRANSLATE_XNo action.
5STEP_TRANSLATE_YNo action.
6STEP_TRANSLATE_ZNo action.
7STEP_YAWRotate the user's avatar about its y-axis in a step increment, if - * the camera isn't in independent or mirror modes.
8PITCHRotate the user's avatar head and attached camera about its negative - * x-axis (i.e., positive values pitch down) at a rate proportional to the control value, if the camera isn't in HMD, - * independent, or mirror modes.
9ZOOMZoom the camera in or out.
10DELTA_YAWRotate the user's avatar about its y-axis by an amount proportional - * to the control value, if the camera isn't in independent or mirror modes.
11DELTA_PITCHRotate the user's avatar head and attached camera about its - * negative x-axis (i.e., positive values pitch down) by an amount proportional to the control value, if the camera - * isn't in HMD, independent, or mirror modes.
{@link DriveKeys|DriveKeys.TRANSLATE_X}Move the user's avatar in the direction of its + * x-axis, if the camera isn't in independent or mirror modes.
{@link DriveKeys|DriveKeys.TRANSLATE_Y}Move the user's avatar in the direction of its + * -axis, if the camera isn't in independent or mirror modes.
{@link DriveKeys|DriveKeys.TRANSLATE_Z}Move the user's avatar in the direction of its + * z-axis, if the camera isn't in independent or mirror modes.
{@link DriveKeys|DriveKeys.YAW}Rotate the user's avatar about its y-axis at a rate + * proportional to the control value, if the camera isn't in independent or mirror modes.
{@link DriveKeys|DriveKeys.STEP_TRANSLATE_X}No action.
{@link DriveKeys|DriveKeys.STEP_TRANSLATE_Y}No action.
{@link DriveKeys|DriveKeys.STEP_TRANSLATE_Z}No action.
{@link DriveKeys|DriveKeys.STEP_YAW}Rotate the user's avatar about its y-axis in a + * step increment, if the camera isn't in independent or mirror modes.
{@link DriveKeys|DriveKeys.PITCH}Rotate the user's avatar head and attached camera + * about its negative x-axis (i.e., positive values pitch down) at a rate proportional to the control value, if the + * camera isn't in HMD, independent, or mirror modes.
{@link DriveKeys|DriveKeys.ZOOM}Zoom the camera in or out.
{@link DriveKeys|DriveKeys.DELTA_YAW}Rotate the user's avatar about its y-axis by an + * amount proportional to the control value, if the camera isn't in independent or mirror modes.
{@link DriveKeys|DriveKeys.DELTA_PITCH}Rotate the user's avatar head and attached + * camera about its negative x-axis (i.e., positive values pitch down) by an amount proportional to the control + * value, if the camera isn't in HMD, independent, or mirror modes.
- * @typedef {number} MyAvatar.DriveKeys + * @typedef {number} DriveKey */ enum DriveKeys { TRANSLATE_X = 0, @@ -1053,7 +1053,7 @@ public: /**jsdoc * Gets the value of a drive key, regardless of whether it is disabled. * @function MyAvatar.getRawDriveKey - * @param {MyAvatar.DriveKeys} key - The drive key. + * @param {DriveKey} key - The drive key. * @returns {number} The value of the drive key. */ Q_INVOKABLE float getRawDriveKey(DriveKeys key) const; @@ -1063,11 +1063,10 @@ public: /**jsdoc * Disables the action associated with a drive key. * @function MyAvatar.disableDriveKey - * @param {MyAvatar.DriveKeys} key - The drive key to disable. + * @param {DriveKey} key - The drive key to disable. * @example Disable rotating your avatar using the keyboard for a couple of seconds. - * var YAW = 3; * print("Disable"); - * MyAvatar.disableDriveKey(YAW); + * MyAvatar.disableDriveKey(DriveKeys.YAW); * Script.setTimeout(function () { * print("Enable"); * MyAvatar.enableDriveKey(YAW); @@ -1079,14 +1078,14 @@ public: * Enables the action associated with a drive key. The action may have been disabled with * {@link MyAvatar.disableDriveKey|disableDriveKey}. * @function MyAvatar.enableDriveKey - * @param {MyAvatar.DriveKeys} key - The drive key to enable. + * @param {DriveKey} key - The drive key to enable. */ Q_INVOKABLE void enableDriveKey(DriveKeys key); /**jsdoc * Checks whether a drive key is disabled. * @function MyAvatar.isDriveKeyDisabled - * @param {DriveKeys} key - The drive key to check. + * @param {DriveKey} key - The drive key to check. * @returns {boolean} true if the drive key is disabled, false if it isn't. */ Q_INVOKABLE bool isDriveKeyDisabled(DriveKeys key) const; From 064e97aa4c24adc3104ceac4c7f02fe661b18124 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 6 Dec 2019 21:27:50 +1300 Subject: [PATCH 06/15] Fix misc. JSDoc typo --- libraries/pointers/src/Pick.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/pointers/src/Pick.h b/libraries/pointers/src/Pick.h index e4257140fd..9e6c5f9898 100644 --- a/libraries/pointers/src/Pick.h +++ b/libraries/pointers/src/Pick.h @@ -93,7 +93,7 @@ public: * collisions. */ - /**jsdoc + /**jsdoc *

A type of pick.

* * From 2b7d66c710923459c1b4e0c3bd7aea162a3b7d4b Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 6 Dec 2019 10:32:45 -0800 Subject: [PATCH 07/15] Slight optimization; comments --- domain-server/src/DomainServer.cpp | 38 +++++++++++-------- domain-server/src/DomainServer.h | 2 +- .../ScreenshareScriptingInterface.cpp | 7 ++++ 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 9a8033e03c..c2de9c78ce 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -3616,28 +3616,18 @@ void DomainServer::handleOctreeFileReplacementRequest(QSharedPointer message) { - QUuid avatar = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID)); - QUuid zone = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID)); + QUuid avatarID = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID)); + QUuid zoneID = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID)); - if (avatar.isNull()) { + if (avatarID.isNull()) { qCWarning(domain_server) << "Ignoring null avatar presence"; return; } - auto limitedNodeList = DependencyManager::get(); - auto matchingNode = limitedNodeList->nodeWithUUID(avatar); - if (!matchingNode) { - qCWarning(domain_server) << "Ignoring avatar presence for unknown avatar" << avatar; - return; - } - QString verifiedUsername = matchingNode->getPermissions().getVerifiedUserName(); - if (verifiedUsername.isEmpty()) { // Silently bail for users who are not logged in. - return; - } static const int SCREENSHARE_EXPIRATION_SECONDS = 24 * 60 * 60; - screensharePresence(zone.isNull() ? "" : zone.toString(), verifiedUsername, avatar, SCREENSHARE_EXPIRATION_SECONDS); + screensharePresence(zoneID.isNull() ? "" : zoneID.toString(), avatarID, SCREENSHARE_EXPIRATION_SECONDS); } -void DomainServer::screensharePresence(QString roomname, QString username, QUuid avatarID, int expirationSeconds) { +void DomainServer::screensharePresence(QString roomname, QUuid avatarID, int expirationSeconds) { if (!DependencyManager::get()->hasValidAccessToken()) { static std::once_flag presenceAuthorityWarning; std::call_once(presenceAuthorityWarning, [] { @@ -3645,10 +3635,25 @@ void DomainServer::screensharePresence(QString roomname, QString username, QUuid }); return; } + + auto limitedNodeList = DependencyManager::get(); + auto matchingNode = limitedNodeList->nodeWithUUID(avatarID); + if (!matchingNode) { + qCWarning(domain_server) << "Ignoring avatar presence for unknown avatar ID" << avatarID; + return; + } + QString verifiedUsername = matchingNode->getPermissions().getVerifiedUserName(); + if (verifiedUsername.isEmpty()) { // Silently bail for users who are not logged in. + return; + } + JSONCallbackParameters callbackParams; callbackParams.callbackReceiver = this; callbackParams.jsonCallbackMethod = "handleSuccessfulScreensharePresence"; callbackParams.errorCallbackMethod = "handleFailedScreensharePresence"; + // Construct `callbackData`, which is data that will be available to the callback functions. + // In this case, the "success" callback needs access to the "roomname" (the zone ID) and the + // relevant avatar's UUID. QJsonObject callbackData; callbackData.insert("roomname", roomname); callbackData.insert("avatarID", avatarID.toString()); @@ -3656,7 +3661,7 @@ void DomainServer::screensharePresence(QString roomname, QString username, QUuid const QString PATH = "api/v1/domains/%1/screenshare"; QString domain_id = uuidStringWithoutCurlyBraces(getID()); QJsonObject json, screenshare; - screenshare["username"] = username; + screenshare["username"] = verifiedUsername; screenshare["roomname"] = roomname; if (expirationSeconds > 0) { screenshare["expiration"] = expirationSeconds; @@ -3677,6 +3682,7 @@ void DomainServer::handleSuccessfulScreensharePresence(QNetworkReply* requestRep return; } + // Tell the client that we just authorized to screenshare which zone ID in which they are authorized to screenshare. auto nodeList = DependencyManager::get(); auto packet = NLPacket::create(PacketType::AvatarZonePresence, NUM_BYTES_RFC4122_UUID, true); packet->write(QUuid(callbackData["roomname"].toString()).toRfc4122()); diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 92ef5a90b3..95b4b784cb 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -78,7 +78,7 @@ public: bool isAssetServerEnabled(); - void screensharePresence(QString roomname, QString username, QUuid avatarID, int expiration_seconds = 0); + void screensharePresence(QString roomname, QUuid avatarID, int expiration_seconds = 0); public slots: /// Called by NodeList to inform us a node has been added diff --git a/interface/src/scripting/ScreenshareScriptingInterface.cpp b/interface/src/scripting/ScreenshareScriptingInterface.cpp index 1e03e90482..3bf8336fe4 100644 --- a/interface/src/scripting/ScreenshareScriptingInterface.cpp +++ b/interface/src/scripting/ScreenshareScriptingInterface.cpp @@ -39,6 +39,7 @@ ScreenshareScriptingInterface::ScreenshareScriptingInterface() { _requestScreenshareInfoRetryTimer->setInterval(SCREENSHARE_INFO_REQUEST_RETRY_TIMEOUT_MS); connect(_requestScreenshareInfoRetryTimer, &QTimer::timeout, this, &ScreenshareScriptingInterface::requestScreenshareInfo); + // This packet listener handles the packet containing information about the latest zone ID in which we are allowed to share. auto nodeList = DependencyManager::get(); PacketReceiver& packetReceiver = nodeList->getPacketReceiver(); packetReceiver.registerListener(PacketType::AvatarZonePresence, this, "processAvatarZonePresencePacketOnClient"); @@ -56,8 +57,11 @@ void ScreenshareScriptingInterface::processAvatarZonePresencePacketOnClient(QSha return; } + // Set the last known authorized screenshare zone ID to the zone that the Domain Server just told us about. _lastAuthorizedZoneID = zone; + // If we had previously started the screenshare process but knew that we weren't going to be authorized to screenshare, + // let's continue the screenshare process here. if (_waitingForAuthorization) { requestScreenshareInfo(); } @@ -65,6 +69,9 @@ void ScreenshareScriptingInterface::processAvatarZonePresencePacketOnClient(QSha static const int MAX_NUM_SCREENSHARE_INFO_REQUEST_RETRIES = 5; void ScreenshareScriptingInterface::requestScreenshareInfo() { + // If the screenshare zone that we're currently in (i.e. `startScreenshare()` was called) is different from + // the zone in which we are authorized to screenshare... + // ...return early here and wait for the DS to send us a packet containing this zone's ID. if (_screenshareZoneID != _lastAuthorizedZoneID) { qDebug() << "Client not yet authorized to screenshare. Waiting for authorization message from domain server..."; _waitingForAuthorization = true; From fbc62df5d8e22b629f7044c91d18c2150a4b5bef Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 7 Dec 2019 19:37:43 +1300 Subject: [PATCH 08/15] Account and GlobalServices JSDoc --- .../AccountServicesScriptingInterface.h | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/interface/src/scripting/AccountServicesScriptingInterface.h b/interface/src/scripting/AccountServicesScriptingInterface.h index 3ad637d0e6..288137e166 100644 --- a/interface/src/scripting/AccountServicesScriptingInterface.h +++ b/interface/src/scripting/AccountServicesScriptingInterface.h @@ -46,6 +46,7 @@ class AccountServicesScriptingInterface : public QObject { * @hifi-avatar * * @namespace AccountServices + * * @property {string} username - The user name of the user logged in. If there is no user logged in, it is * "Unknown user". Read-only. * @property {boolean} loggedIn - true if the user is logged in, otherwise false. @@ -61,6 +62,86 @@ class AccountServicesScriptingInterface : public QObject { * — typically "https://metaverse.highfidelity.com". Read-only. */ + /**jsdoc + * The Account API provides functions that give information on user connectivity, visibility, and asset + * download progress. + * + * @deprecated This API is the same as the {@link AccountServices} API and will be removed. + * + * @hifi-interface + * @hifi-client-entity + * @hifi-avatar + * + * @namespace Account + * + * @property {string} username - The user name of the user logged in. If there is no user logged in, it is + * "Unknown user". Read-only. + * @property {boolean} loggedIn - true if the user is logged in, otherwise false. + * Read-only. + * @property {string} findableBy - The user's visibility to other users: + *
    + *
  • "none" — user appears offline.
  • + *
  • "friends" — user is visible only to friends.
  • + *
  • "connections" — user is visible to friends and connections.
  • + *
  • "all" — user is visible to everyone.
  • + *
+ * @property {string} metaverseServerURL - The metaverse server that the user is authenticated against when logged in + * — typically "https://metaverse.highfidelity.com". Read-only. + * + * @borrows AccountServices.getDownloadInfo as getDownloadInfo + * @borrows AccountServices.updateDownloadInfo as updateDownloadInfo + * @borrows AccountServices.isLoggedIn as isLoggedIn + * @borrows AccountServices.checkAndSignalForAccessToken as checkAndSignalForAccessToken + * @borrows AccountServices.logOut as logOut + * + * @borrows AccountServices.connected as connected + * @borrows AccountServices.disconnected as disconnected + * @borrows AccountServices.myUsernameChanged as myUsernameChanged + * @borrows AccountServices.downloadInfoChanged as downloadInfoChanged + * @borrows AccountServices.findableByChanged as findableByChanged + * @borrows AccountServices.loggedInChanged as loggedInChanged + */ + + /**jsdoc + * The GlobalServices API provides functions that give information on user connectivity, visibility, and asset + * download progress. + * + * @deprecated This API is the same as the {@link AccountServices} API and will be removed. + * + * @hifi-interface + * @hifi-client-entity + * @hifi-avatar + * + * @namespace GlobalServices + * + * @property {string} username - The user name of the user logged in. If there is no user logged in, it is + * "Unknown user". Read-only. + * @property {boolean} loggedIn - true if the user is logged in, otherwise false. + * Read-only. + * @property {string} findableBy - The user's visibility to other users: + *
    + *
  • "none" — user appears offline.
  • + *
  • "friends" — user is visible only to friends.
  • + *
  • "connections" — user is visible to friends and connections.
  • + *
  • "all" — user is visible to everyone.
  • + *
+ * @property {string} metaverseServerURL - The metaverse server that the user is authenticated against when logged in + * — typically "https://metaverse.highfidelity.com". Read-only. + * + * @borrows AccountServices.getDownloadInfo as getDownloadInfo + * @borrows AccountServices.updateDownloadInfo as updateDownloadInfo + * @borrows AccountServices.isLoggedIn as isLoggedIn + * @borrows AccountServices.checkAndSignalForAccessToken as checkAndSignalForAccessToken + * @borrows AccountServices.logOut as logOut + * + * @borrows AccountServices.connected as connected + * @borrows AccountServices.disconnected as disconnected + * @borrows AccountServices.myUsernameChanged as myUsernameChanged + * @borrows AccountServices.downloadInfoChanged as downloadInfoChanged + * @borrows AccountServices.findableByChanged as findableByChanged + * @borrows AccountServices.loggedInChanged as loggedInChanged + */ + Q_PROPERTY(QString username READ getUsername NOTIFY myUsernameChanged) Q_PROPERTY(bool loggedIn READ loggedIn NOTIFY loggedInChanged) Q_PROPERTY(QString findableBy READ getFindableBy WRITE setFindableBy NOTIFY findableByChanged) From 31bae651c610746a2892b231de779d7839e38d91 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 8 Dec 2019 15:51:08 +1300 Subject: [PATCH 09/15] DialogsManager JSDoc --- .../DialogsManagerScriptingInterface.h | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/interface/src/scripting/DialogsManagerScriptingInterface.h b/interface/src/scripting/DialogsManagerScriptingInterface.h index b223799cfe..ee1baeecf5 100644 --- a/interface/src/scripting/DialogsManagerScriptingInterface.h +++ b/interface/src/scripting/DialogsManagerScriptingInterface.h @@ -14,19 +14,56 @@ #include +/**jsdoc + * The DialogsMamnager API provides facilities to work with some key dialogs. + * + * @namespace DialogsManager + * + * @hifi-interface + * @hifi-client-entity + * @hifi-avatar + */ + class DialogsManagerScriptingInterface : public QObject { Q_OBJECT public: DialogsManagerScriptingInterface(); static DialogsManagerScriptingInterface* getInstance(); + + /**jsdoc + * Currently performs no action. + * @function DialogsManager.showFeed + */ Q_INVOKABLE void showFeed(); public slots: + /**jsdoc + * Shows the "Goto" dialog. + * @function DialogsManager.showAddressBar + */ void showAddressBar(); + + /**jsdoc + * Hides the "Goto" dialog. + * @function DialogsManager.hideAddressBar + */ void hideAddressBar(); + + /**jsdoc + * Shows the login dialog. + * @function DialogsManager.showLoginDialog + */ void showLoginDialog(); signals: + /**jsdoc + * Triggered when the "Goto" dialog is opened or closed. + *

Warning: Currently isn't always triggered.

+ * @function DialogsManager.addressBarShown + * @param {boolean} visible - true if the Goto dialog has been opened, false if it has been + * closed. + * @returns {Signal} + */ void addressBarShown(bool visible); }; From 3a48a97a90da357b3ec483aaa476674a81541f40 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 10 Dec 2019 07:34:17 +1300 Subject: [PATCH 10/15] AddressManager JSDoc --- libraries/networking/src/AddressManager.h | 60 +++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index 7a67371ab5..655b2901de 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -68,6 +68,66 @@ const QString GET_PLACE = "/api/v1/places/%1"; * Read-only. */ +/**jsdoc + * The AddressMAnager API provides facilities related to your current location in the metaverse. + * + * @namespace AddressManager + * + * @hifi-interface + * @hifi-client-entity + * @hifi-avatar + * + * @deprecated This API is deprecated and will be removed. Use the {@link location} or {@link Window|Window.location} APIs + * instead. + * + * @property {Uuid} domainID - A UUID uniquely identifying the domain you're visiting. Is {@link Uuid(0)|Uuid.NULL} if you're not + * connected to the domain or are in a serverless domain. + * Read-only. + * @property {string} hostname - The name of the domain for your current metaverse address (e.g., "DomainName", + * localhost, or an IP address). Is blank if you're in a serverless domain. + * Read-only. + * @property {string} href - Your current metaverse address (e.g., "hifi://domainname/15,-10,26/0,0,0,1") + * regardless of whether or not you're connected to the domain. Starts with "file:///" if you're in a + * serverless domain. + * Read-only. + * @property {boolean} isConnected - true if you're connected to the domain in your current href + * metaverse address, otherwise false. + * @property {string} pathname - The location and orientation in your current href metaverse address + * (e.g., "/15,-10,26/0,0,0,1"). + * Read-only. + * @property {string} placename - The place name in your current href metaverse address + * (e.g., "DomainName"). Is blank if your hostname is an IP address. + * Read-only. + * @property {string} protocol - The protocol of your current href metaverse address (e.g., "hifi"). + * Read-only. + * + * @borrows location.handleLookupString as handleLookupString + * @borrows location.goToViewpointForPath as goToViewpointForPath + * @borrows location.goBack as goBack + * @borrows location.goForward as goForward + * @borrows location.goToLocalSandbox as goToLocalSandbox + * @borrows location.goToEntry as goToEntry + * @borrows location.goToUser as goToUser + * @borrows location.goToLastAddress as goToLastAddress + * @borrows location.canGoBack as canGoBack + * @borrows location.refreshPreviousLookup as refreshPreviousLookup + * @borrows location.storeCurrentAddress as storeCurrentAddress + * @borrows location.copyAddress as copyAddress + * @borrows location.copyPath as copyPath + * @borrows location.lookupShareableNameForDomainID as lookupShareableNameForDomainID + * + * @borrows location.lookupResultsFinished as lookupResultsFinished + * @borrows location.lookupResultIsOffline as lookupResultIsOffline + * @borrows location.lookupResultIsNotFound as lookupResultIsNotFound + * @borrows location.possibleDomainChangeRequired as possibleDomainChangeRequired + * @borrows location.locationChangeRequired as locationChangeRequired + * @borrows location.possibleDomainChangeRequiredViaICEForID as possibleDomainChangeRequiredViaICEForID + * @borrows location.pathChangeRequired as pathChangeRequired + * @borrows location.hostChanged as hostChanged + * @borrows location.goBackPossible as goBackPossible + * @borrows location.goForwardPossible as goForwardPossible + */ + class AddressManager : public QObject, public Dependency { Q_OBJECT SINGLETON_DEPENDENCY From 204215c57325daa2285725cb3de77f95f87268c2 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 10 Dec 2019 07:49:37 +1300 Subject: [PATCH 11/15] Typo --- libraries/networking/src/AddressManager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index 655b2901de..8bdb777f96 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -69,7 +69,7 @@ const QString GET_PLACE = "/api/v1/places/%1"; */ /**jsdoc - * The AddressMAnager API provides facilities related to your current location in the metaverse. + * The AddressManager API provides facilities related to your current location in the metaverse. * * @namespace AddressManager * From 86dd2e2c3bf98eaebbf97ad26043c434d74bb42a Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 9 Dec 2019 09:48:51 -0800 Subject: [PATCH 12/15] Fix windows PR installer build, switch to matrix PR builds --- .github/workflows/master_build.yml | 1 - .github/workflows/pr_build.yml | 90 ++++++++++++++++-------------- 2 files changed, 49 insertions(+), 42 deletions(-) diff --git a/.github/workflows/master_build.yml b/.github/workflows/master_build.yml index 314578d01d..6f87f59d1d 100644 --- a/.github/workflows/master_build.yml +++ b/.github/workflows/master_build.yml @@ -91,7 +91,6 @@ jobs: # - os: ubuntu-latest # build_type: client runs-on: ${{matrix.os}} - if: github.event.action != 'labeled' || github.event.label.name == 'rebuild-mac' || github.event.label.name == 'rebuild' needs: generate_build_number steps: - name: Download build number diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index 095364dd7e..5b643545cb 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -9,80 +9,88 @@ env: BUILD_TYPE: Release CI_BUILD: Github GIT_COMMIT: ${{ github.sha }} - GIT_COMMIT_SHORT: ${{ github.sha }} HIFI_VCPKG_BOOTSTRAP: true RELEASE_TYPE: PR RELEASE_NUMBER: ${{ github.event.number }} VERSION_CODE: ${{ github.event.number }} + # OSX specific variables DEVELOPER_DIR: /Applications/Xcode_11.2.app/Contents/Developer MACOSX_DEPLOYMENT_TARGET: '10.11' # WIN32 specific variables PreferredToolArchitecture: X64 + GIT_COMMIT_SHORT: ${{ github.sha }} + jobs: - build_full_mac: - runs-on: macOS-latest - if: github.event.action != 'labeled' || github.event.label.name == 'rebuild-mac' || github.event.label.name == 'rebuild' + build: + strategy: + matrix: + os: [windows-latest, macOS-latest] + build_type: [full] + runs-on: ${{matrix.os}} + if: github.event.action != 'labeled' || github.event.label.name == 'rebuild' steps: + - name: Configure Build Environment 1 + shell: bash + id: buildenv1 + run: | + echo ::set-env name=GIT_COMMIT_SHORT::`echo $GIT_COMMIT | cut -c1-7` + # Linux build variables + if [ "${{ matrix.os }}" = "ubuntu-latest" ]; then + echo ::set-env name=PYTHON_EXEC::python3 + echo ::set-env name=INSTALLER_EXT::tgz + fi + # Mac build variables + if [ "${{ matrix.os }}" = "macOS-latest" ]; then + echo ::set-env name=PYTHON_EXEC::python3 + echo ::set-env name=INSTALLER_EXT::dmg + echo ::set-env name=CMAKE_EXTRA::"-DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED=OFF -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl -G Xcode" + fi + # Windows build variables + if [ "${{ matrix.os }}" = "windows-latest" ]; then + echo ::set-env name=PYTHON_EXEC::python + echo ::set-env name=INSTALLER_EXT::exe + echo ::set-env name=CMAKE_EXTRA::"-A x64" + fi + # Configureation is broken into two steps because you can't set an env var and also reference it in the same step + - name: Configure Build Environment 2 + shell: bash + run: | + echo "${{ steps.buildenv1.outputs.symbols_archive }}" + echo ::set-env name=ARTIFACT_PATTERN::HighFidelity-Beta-*.$INSTALLER_EXT + # Build type variables + echo ::set-env name=INSTALLER::HighFidelity-Beta-$RELEASE_NUMBER-$GIT_COMMIT_SHORT.$INSTALLER_EXT - uses: actions/checkout@v1 with: submodules: true fetch-depth: 1 - name: Create Build Environment - run: cmake -E make_directory ${{runner.workspace}}/build + shell: bash + run: cmake -E make_directory "${{runner.workspace}}/build" - name: Configure CMake working-directory: ${{runner.workspace}}/build - run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED=OFF -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl -G Xcode -DVCPKG_APPLOCAL_DEPS=OFF - - name: Build Console - working-directory: ${{runner.workspace}}/build - run: cmake --build . --config $BUILD_TYPE --target packaged-server-console + shell: bash + run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE $CMAKE_EXTRA - name: Build Application working-directory: ${{runner.workspace}}/build + shell: bash run: cmake --build . --config $BUILD_TYPE --target $APP_NAME - name: Build Domain Server working-directory: ${{runner.workspace}}/build + shell: bash run: cmake --build . --config $BUILD_TYPE --target domain-server - name: Build Assignment Client working-directory: ${{runner.workspace}}/build - run: cmake --build . --config $BUILD_TYPE --target assignment-client - - name: Build Installer - working-directory: ${{runner.workspace}}/build - run: cmake --build . --config $BUILD_TYPE --target package - - build_full_win32: - runs-on: windows-latest - if: github.event.action != 'labeled' || github.event.label.name == 'rebuild-win' || github.event.label.name == 'rebuild' - steps: - - uses: actions/checkout@v1 - with: - submodules: true - fetch-depth: 1 - - name: Create Build Environment - run: cmake -E make_directory ${{runner.workspace}}/build - - name: Configure CMake shell: bash - working-directory: ${{runner.workspace}}/build - run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -A x64 + run: cmake --build . --config $BUILD_TYPE --target assignment-client - name: Build Console - shell: bash working-directory: ${{runner.workspace}}/build + shell: bash run: cmake --build . --config $BUILD_TYPE --target packaged-server-console - - name: Build Application - shell: bash - working-directory: ${{runner.workspace}}/build - run: cmake --build . --config $BUILD_TYPE --target $APP_NAME - - name: Build Domain Server - shell: bash - working-directory: ${{runner.workspace}}/build - run: cmake --build . --config $BUILD_TYPE --target domain-server - - name: Build Assignment Client - shell: bash - working-directory: ${{runner.workspace}}/build - run: cmake --build . --config $BUILD_TYPE --target assignment-client - name: Build Installer - shell: bash working-directory: ${{runner.workspace}}/build + shell: bash run: cmake --build . --config $BUILD_TYPE --target package From b7af7fe1ab315c620fa18a9c613a756a2dbbbadd Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 23 Oct 2019 09:54:00 +1300 Subject: [PATCH 13/15] OffscreenFlags JSDoc --- libraries/ui/src/OffscreenUi.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index f0b27904ae..1aa14cb9f8 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -33,13 +33,22 @@ #include "MainWindow.h" /**jsdoc + * The OffscreenFlags API enables gamepad joystick navigation of UI. + * + *

This API no longer works.

+ * * @namespace OffscreenFlags * * @hifi-interface * @hifi-client-entity * @hifi-avatar - * @property {boolean} navigationFocused - * @property {boolean} navigationFocusDisabled + * + * @property {boolean} navigationFocused - true if UI has joystick navigation focus, false if it + * doesn't. + * @property {boolean} navigationFocusDisabled - true if UI joystick navigation focus is disabled, + * false if it isn't. + * + * @deprecated This API is deprecated and will be removed. */ // Needs to match the constants in resources/qml/Global.js @@ -72,12 +81,14 @@ public: signals: /**jsdoc + * Triggered when the value of the navigationFocused property changes. * @function OffscreenFlags.navigationFocusedChanged * @returns {Signal} */ void navigationFocusedChanged(); /**jsdoc + * Triggered when the value of the navigationFocusDisabled property changes. * @function OffscreenFlags.navigationFocusDisabledChanged * @returns {Signal} */ From deb60f66d09fd1380dd4fa7093bc11f5bfb8b8d0 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 10 Dec 2019 09:20:12 +1300 Subject: [PATCH 14/15] Update API status --- libraries/ui/src/OffscreenUi.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index 1aa14cb9f8..34184057e0 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -35,7 +35,7 @@ /**jsdoc * The OffscreenFlags API enables gamepad joystick navigation of UI. * - *

This API no longer works.

+ *

This API currently has no effect and is not used.

* * @namespace OffscreenFlags * @@ -47,8 +47,6 @@ * doesn't. * @property {boolean} navigationFocusDisabled - true if UI joystick navigation focus is disabled, * false if it isn't. - * - * @deprecated This API is deprecated and will be removed. */ // Needs to match the constants in resources/qml/Global.js From ca729cba4f23c5c004da9e48599ad03bf62e9919 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 9 Dec 2019 12:58:52 -0800 Subject: [PATCH 15/15] Disable PR builds from labels --- .github/workflows/pr_build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index 5b643545cb..9dae719618 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -2,7 +2,7 @@ name: Pull Request CI Build on: pull_request: - types: [opened, synchronize, reopened, labeled] + types: [opened, synchronize, reopened] env: APP_NAME: interface