From 3712e1453073d040ae127100cde04de17dd4dc4d Mon Sep 17 00:00:00 2001 From: Liv Date: Tue, 18 Jul 2017 10:02:46 -0700 Subject: [PATCH 01/54] Surface new user group UI to domain server settings --- .../resources/describe-settings.json | 191 ++++++++++++------ 1 file changed, 127 insertions(+), 64 deletions(-) diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index c1eff76d78..8d0e949ff3 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -1,5 +1,5 @@ { - "version": 1.7, + "version": 1.8, "settings": [ { "name": "metaverse", @@ -112,7 +112,6 @@ "label": "Adult (18+)" } ] - }, { "name": "hosts", @@ -161,15 +160,15 @@ "label": "HTTP Password", "type": "password", "help": "Password used for basic HTTP authentication. Leave this alone if you do not want to change it.", - "password_placeholder" : "******", + "password_placeholder": "******", "value-hidden": true }, { - "name": "verify_http_password", - "label": "Verify HTTP Password", - "type": "password", - "help": "Must match the password entered above for change to be saved.", - "value-hidden": true + "name": "verify_http_password", + "label": "Verify HTTP Password", + "type": "password", + "help": "Must match the password entered above for change to be saved.", + "value-hidden": true }, { "name": "maximum_user_capacity", @@ -208,21 +207,19 @@ "name": "standard_permissions", "type": "table", "label": "Domain-Wide User Permissions", - "help": "Indicate which types of users can have which domain-wide permissions.", + "help": "Indicate which types of users can have which domain-wide permissions.", "caption": "Standard Permissions", "can_add_new_rows": false, - "groups": [ { "label": "Type of User", "span": 1 }, { - "label": "Permissions ?", - "span": 7 + "label": "Permissions ?", + "span": 8 } ], - "columns": [ { "name": "permissions_id", @@ -276,9 +273,15 @@ "type": "checkbox", "editable": true, "default": false + }, + { + "name": "id_can_replace_content", + "label": "Replace Content", + "type": "checkbox", + "editable": true, + "default": false } ], - "non-deletable-row-key": "permissions_id", "non-deletable-row-values": ["localhost", "anonymous", "logged-in"] }, @@ -291,18 +294,16 @@ "can_add_new_rows": false, "new_category_placeholder": "Add Group", "new_category_message": "Save and reload to see ranks", - "groups": [ { "label": "Rank", "span": 1 }, { - "label": "Permissions ?", - "span": 7 + "label": "Permissions ?", + "span": 8 } ], - "columns": [ { "name": "permissions_id", @@ -381,6 +382,13 @@ "type": "checkbox", "editable": true, "default": false + }, + { + "name": "id_can_replace_content", + "label": "Replace Content", + "type": "checkbox", + "editable": true, + "default": false } ] }, @@ -393,18 +401,16 @@ "can_add_new_rows": false, "new_category_placeholder": "Add Blacklist Group", "new_category_message": "Save and reload to see ranks", - "groups": [ { "label": "Rank", "span": 1 }, { - "label": "Permissions ?", - "span": 7 + "label": "Permissions ?", + "span": 8 } ], - "columns": [ { "name": "permissions_id", @@ -480,6 +486,13 @@ "type": "checkbox", "editable": true, "default": false + }, + { + "name": "id_can_replace_content", + "label": "Replace Content", + "type": "checkbox", + "editable": true, + "default": false } ] }, @@ -488,18 +501,16 @@ "type": "table", "caption": "Permissions for Specific Users", "can_add_new_rows": true, - "groups": [ { "label": "User", "span": 1 }, { - "label": "Permissions ?", - "span": 7 + "label": "Permissions ?", + "span": 8 } ], - "columns": [ { "name": "permissions_id", @@ -553,6 +564,13 @@ "type": "checkbox", "editable": true, "default": false + }, + { + "name": "id_can_replace_content", + "label": "Replace Content", + "type": "checkbox", + "editable": true, + "default": false } ] }, @@ -567,11 +585,10 @@ "span": 1 }, { - "label": "Permissions ?", - "span": 7 + "label": "Permissions ?", + "span": 8 } ], - "columns": [ { "name": "permissions_id", @@ -625,6 +642,13 @@ "type": "checkbox", "editable": true, "default": false + }, + { + "name": "id_can_replace_content", + "label": "Replace Content", + "type": "checkbox", + "editable": true, + "default": false } ] }, @@ -639,11 +663,10 @@ "span": 1 }, { - "label": "Permissions ?", - "span": 7 + "label": "Permissions ?", + "span": 8 } ], - "columns": [ { "name": "permissions_id", @@ -697,6 +720,13 @@ "type": "checkbox", "editable": true, "default": false + }, + { + "name": "id_can_replace_content", + "label": "Replace Content", + "type": "checkbox", + "editable": true, + "default": false } ] }, @@ -711,11 +741,10 @@ "span": 1 }, { - "label": "Permissions ?", - "span": 7 + "label": "Permissions ?", + "span": 8 } ], - "columns": [ { "name": "permissions_id", @@ -769,6 +798,13 @@ "type": "checkbox", "editable": true, "default": false + }, + { + "name": "id_can_replace_content", + "label": "Replace Content", + "type": "checkbox", + "editable": true, + "default": false } ] } @@ -784,7 +820,6 @@ "label": "Persistent Scripts", "help": "Add the URLs for scripts that you would like to ensure are always running in your domain.", "can_add_new_rows": true, - "columns": [ { "name": "url", @@ -946,7 +981,6 @@ "help": "In this table you can define a set of zones in which you can specify various audio properties.", "numbered": false, "can_add_new_rows": true, - "key": { "name": "name", "label": "Name", @@ -999,7 +1033,6 @@ "numbered": true, "can_order": true, "can_add_new_rows": true, - "columns": [ { "name": "source", @@ -1028,7 +1061,6 @@ "help": "In this table you can set reverb levels for audio zones. For a medium-sized (e.g., 100 square meter) meeting room, try a decay time of around 1.5 seconds and a wet/dry mix of 25%. For an airplane hangar or cathedral, try a decay time of 4 seconds and a wet/dry mix of 50%.", "numbered": true, "can_add_new_rows": true, - "columns": [ { "name": "zone", @@ -1063,7 +1095,9 @@ { "name": "audio_buffer", "label": "Audio Buffers", - "assignment-types": [0], + "assignment-types": [ + 0 + ], "settings": [ { "name": "dynamic_jitter_buffer", @@ -1082,35 +1116,37 @@ "advanced": true }, { - "name": "max_frames_over_desired", - "deprecated": true + "name": "max_frames_over_desired", + "deprecated": true }, { - "name": "window_starve_threshold", - "deprecated": true + "name": "window_starve_threshold", + "deprecated": true }, { - "name": "window_seconds_for_desired_calc_on_too_many_starves", - "deprecated": true + "name": "window_seconds_for_desired_calc_on_too_many_starves", + "deprecated": true }, { - "name": "window_seconds_for_desired_reduction", - "deprecated": true + "name": "window_seconds_for_desired_reduction", + "deprecated": true }, { - "name": "use_stdev_for_desired_calc", - "deprecated": true + "name": "use_stdev_for_desired_calc", + "deprecated": true }, { - "name": "repetition_with_fade", - "deprecated": true + "name": "repetition_with_fade", + "deprecated": true } ] }, { "name": "entity_server_settings", "label": "Entity Server Settings", - "assignment-types": [6], + "assignment-types": [ + 6 + ], "settings": [ { "name": "maxTmpLifetime", @@ -1167,13 +1203,32 @@ "help": "In this table you can define a set of rules for how frequently to backup copies of your entites content file.", "numbered": false, "can_add_new_rows": true, - - "default": [ - {"Name":"Half Hourly Rolling","backupInterval":1800,"format":".backup.halfhourly.%N","maxBackupVersions":5}, - {"Name":"Daily Rolling","backupInterval":86400,"format":".backup.daily.%N","maxBackupVersions":7}, - {"Name":"Weekly Rolling","backupInterval":604800,"format":".backup.weekly.%N","maxBackupVersions":4}, - {"Name":"Thirty Day Rolling","backupInterval":2592000,"format":".backup.thirtyday.%N","maxBackupVersions":12} - ], + "default": [ + { + "Name": "Half Hourly Rolling", + "backupInterval": 1800, + "format": ".backup.halfhourly.%N", + "maxBackupVersions": 5 + }, + { + "Name": "Daily Rolling", + "backupInterval": 86400, + "format": ".backup.daily.%N", + "maxBackupVersions": 7 + }, + { + "Name": "Weekly Rolling", + "backupInterval": 604800, + "format": ".backup.weekly.%N", + "maxBackupVersions": 4 + }, + { + "Name": "Thirty Day Rolling", + "backupInterval": 2592000, + "format": ".backup.thirtyday.%N", + "maxBackupVersions": 12 + } + ], "columns": [ { "name": "Name", @@ -1309,7 +1364,9 @@ { "name": "avatar_mixer", "label": "Avatar Mixer", - "assignment-types": [1], + "assignment-types": [ + 1 + ], "settings": [ { "name": "max_node_send_bandwidth", @@ -1362,7 +1419,10 @@ { "name": "downstream_servers", "label": "Receiving Servers", - "assignment-types": [0,1], + "assignment-types": [ + 0, + 1 + ], "type": "table", "advanced": true, "can_add_new_rows": true, @@ -1402,7 +1462,10 @@ { "name": "upstream_servers", "label": "Broadcasting Servers", - "assignment-types": [0,1], + "assignment-types": [ + 0, + 1 + ], "type": "table", "advanced": true, "can_add_new_rows": true, @@ -1442,4 +1505,4 @@ ] } ] -} +} \ No newline at end of file From e0fd3917661d4226637cd7ec4f2c2dddd5d5aaae Mon Sep 17 00:00:00 2001 From: Liv Date: Tue, 18 Jul 2017 14:34:22 -0700 Subject: [PATCH 02/54] Add permission level for replacing domain content --- domain-server/src/DomainGatekeeper.cpp | 2 ++ domain-server/src/DomainServerSettingsManager.cpp | 1 + libraries/networking/src/LimitedNodeList.cpp | 4 ++++ libraries/networking/src/LimitedNodeList.h | 4 +++- libraries/networking/src/Node.h | 1 + libraries/networking/src/NodePermissions.cpp | 5 +++++ libraries/networking/src/NodePermissions.h | 3 ++- libraries/script-engine/src/UsersScriptingInterface.cpp | 4 ++++ libraries/script-engine/src/UsersScriptingInterface.h | 9 +++++++++ 9 files changed, 31 insertions(+), 2 deletions(-) diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index 62f56184f4..9e44dbb9b8 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -269,6 +269,7 @@ void DomainGatekeeper::updateNodePermissions() { userPerms.permissions |= NodePermissions::Permission::canRezPermanentEntities; userPerms.permissions |= NodePermissions::Permission::canRezTemporaryEntities; userPerms.permissions |= NodePermissions::Permission::canWriteToAssetServer; + userPerms.permissions |= NodePermissions::Permission::canReplaceDomainContent; } else { // this node is an agent const QHostAddress& addr = node->getLocalSocket().getAddress(); @@ -357,6 +358,7 @@ SharedNodePointer DomainGatekeeper::processAssignmentConnectRequest(const NodeCo userPerms.permissions |= NodePermissions::Permission::canRezPermanentEntities; userPerms.permissions |= NodePermissions::Permission::canRezTemporaryEntities; userPerms.permissions |= NodePermissions::Permission::canWriteToAssetServer; + userPerms.permissions |= NodePermissions::Permission::canReplaceDomainContent; newNode->setPermissions(userPerms); return newNode; } diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index 7a2cfa645a..dbc6e45b28 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -112,6 +112,7 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList const QString RESTRICTED_ACCESS_SETTINGS_KEYPATH = "security.restricted_access"; const QString ALLOWED_EDITORS_SETTINGS_KEYPATH = "security.allowed_editors"; const QString EDITORS_ARE_REZZERS_KEYPATH = "security.editors_are_rezzers"; + const QString EDITORS_CAN_REPLACE_CONTENT_KEYPATH = "security.editors_can_replace_content"; qDebug() << "Previous domain-server settings version was" << QString::number(oldVersion, 'g', 8) << "and the new version is" diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index eab0e5e41f..56ebc682f7 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -167,6 +167,10 @@ void LimitedNodeList::setPermissions(const NodePermissions& newPermissions) { newPermissions.can(NodePermissions::Permission::canKick)) { emit canKickChanged(_permissions.can(NodePermissions::Permission::canKick)); } + if (originalPermissions.can(NodePermissions::Permission::canReplaceDomainContent) != + newPermissions.can(NodePermissions::Permission::canReplaceDomainContent)) { + emit canReplaceContentChanged(_permissions.can(NodePermissions::Permission::canReplaceDomainContent)); + } } void LimitedNodeList::setSocketLocalPort(quint16 socketLocalPort) { diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 5d602cc0c0..f4ec47636b 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -115,7 +115,8 @@ public: bool getThisNodeCanRezTmp() const { return _permissions.can(NodePermissions::Permission::canRezTemporaryEntities); } bool getThisNodeCanWriteAssets() const { return _permissions.can(NodePermissions::Permission::canWriteToAssetServer); } bool getThisNodeCanKick() const { return _permissions.can(NodePermissions::Permission::canKick); } - + bool getThisNodeCanReplaceContent() const { return _permissions.can(NodePermissions::Permission::canReplaceDomainContent); } + quint16 getSocketLocalPort() const { return _nodeSocket.localPort(); } Q_INVOKABLE void setSocketLocalPort(quint16 socketLocalPort); @@ -329,6 +330,7 @@ signals: void canRezTmpChanged(bool canRezTmp); void canWriteAssetsChanged(bool canWriteAssets); void canKickChanged(bool canKick); + void canReplaceContentChanged(bool canReplaceContent); protected slots: void connectedForLocalSocketTest(); diff --git a/libraries/networking/src/Node.h b/libraries/networking/src/Node.h index c20ff5a395..c4d2153db6 100644 --- a/libraries/networking/src/Node.h +++ b/libraries/networking/src/Node.h @@ -74,6 +74,7 @@ public: bool getCanRezTmp() const { return _permissions.can(NodePermissions::Permission::canRezTemporaryEntities); } bool getCanWriteToAssetServer() const { return _permissions.can(NodePermissions::Permission::canWriteToAssetServer); } bool getCanKick() const { return _permissions.can(NodePermissions::Permission::canKick); } + bool getCanReplaceContent() const { return _permissions.can(NodePermissions::Permission::canReplaceDomainContent); } void parseIgnoreRequestMessage(QSharedPointer message); void addIgnoredNode(const QUuid& otherNodeID); diff --git a/libraries/networking/src/NodePermissions.cpp b/libraries/networking/src/NodePermissions.cpp index a1d4fc182e..cc5df515aa 100644 --- a/libraries/networking/src/NodePermissions.cpp +++ b/libraries/networking/src/NodePermissions.cpp @@ -45,6 +45,7 @@ NodePermissions::NodePermissions(QMap perms) { permissions |= perms["id_can_connect_past_max_capacity"].toBool() ? Permission::canConnectPastMaxCapacity : Permission::none; permissions |= perms["id_can_kick"].toBool() ? Permission::canKick : Permission::none; + permissions |= perms["id_can_replace_content"].toBool() ? Permission::canReplaceDomainContent : Permission::none; } QVariant NodePermissions::toVariant(QHash groupRanks) { @@ -65,6 +66,7 @@ QVariant NodePermissions::toVariant(QHash groupRanks) { values["id_can_write_to_asset_server"] = can(Permission::canWriteToAssetServer); values["id_can_connect_past_max_capacity"] = can(Permission::canConnectPastMaxCapacity); values["id_can_kick"] = can(Permission::canKick); + values["id_can_replace_content"] = can(Permission::canReplaceDomainContent); return QVariant(values); } @@ -128,6 +130,9 @@ QDebug operator<<(QDebug debug, const NodePermissions& perms) { if (perms.can(NodePermissions::Permission::canKick)) { debug << " kick"; } + if (perms.can(NodePermissions::Permission::canReplaceDomainContent)) { + debug << " can_replace_content"; + } debug.nospace() << "]"; return debug.nospace(); } diff --git a/libraries/networking/src/NodePermissions.h b/libraries/networking/src/NodePermissions.h index 6fa005e360..129d7e5c08 100644 --- a/libraries/networking/src/NodePermissions.h +++ b/libraries/networking/src/NodePermissions.h @@ -77,7 +77,8 @@ public: canRezTemporaryEntities = 8, canWriteToAssetServer = 16, canConnectPastMaxCapacity = 32, - canKick = 64 + canKick = 64, + canReplaceDomainContent = 128 }; Q_DECLARE_FLAGS(Permissions, Permission) Permissions permissions; diff --git a/libraries/script-engine/src/UsersScriptingInterface.cpp b/libraries/script-engine/src/UsersScriptingInterface.cpp index 6dc3188b3f..ab8e62040b 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.cpp +++ b/libraries/script-engine/src/UsersScriptingInterface.cpp @@ -19,6 +19,7 @@ UsersScriptingInterface::UsersScriptingInterface() { connect(nodeList.data(), &LimitedNodeList::canKickChanged, this, &UsersScriptingInterface::canKickChanged); connect(nodeList.data(), &NodeList::ignoreRadiusEnabledChanged, this, &UsersScriptingInterface::ignoreRadiusEnabledChanged); connect(nodeList.data(), &NodeList::usernameFromIDReply, this, &UsersScriptingInterface::usernameFromIDReply); + connect(nodeList.data(), &NodeList::canReplaceContentChanged, this, &UsersScriptingInterface::canReplaceContentChanged); } void UsersScriptingInterface::ignore(const QUuid& nodeID, bool ignoreEnabled) { @@ -93,3 +94,6 @@ bool UsersScriptingInterface::getRequestsDomainListData() { void UsersScriptingInterface::setRequestsDomainListData(bool isRequesting) { DependencyManager::get()->setRequestsDomainListData(isRequesting); } +bool UsersScriptingInterface::getCanReplaceContent() { + return DependencyManager::get()->getThisNodeCanReplaceContent(); +} diff --git a/libraries/script-engine/src/UsersScriptingInterface.h b/libraries/script-engine/src/UsersScriptingInterface.h index acaa92d9c8..b39293dc0e 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.h +++ b/libraries/script-engine/src/UsersScriptingInterface.h @@ -25,6 +25,7 @@ class UsersScriptingInterface : public QObject, public Dependency { Q_PROPERTY(bool canKick READ getCanKick) Q_PROPERTY(bool requestsDomainListData READ getRequestsDomainListData WRITE setRequestsDomainListData) + Q_PROPERTY(bool canReplaceContent READ getCanReplaceContent) public: UsersScriptingInterface(); @@ -131,6 +132,13 @@ public slots: */ bool getIgnoreRadiusEnabled(); + /**jsdoc + * Returns true if the user has permissions to replace domain content sets + * @function Users.getCanReplaceContent + * @return {bool} true if the user has permissions to replace domain content sets, false if not + */ + bool getCanReplaceContent(); + signals: void canKickChanged(bool canKick); void ignoreRadiusEnabledChanged(bool isEnabled); @@ -154,6 +162,7 @@ signals: * @param {nodeID} NodeID The session ID of the avatar that has disconnected */ void avatarDisconnected(const QUuid& nodeID); + void canReplaceContentChanged(bool canReplaceContent); private: bool getRequestsDomainListData(); From bdb12c38cf069ec6750083c8e8668207553ada65 Mon Sep 17 00:00:00 2001 From: Liv Date: Thu, 20 Jul 2017 11:41:57 -0700 Subject: [PATCH 03/54] Move API call to Entities scripting and out of Users --- assignment-client/src/octree/OctreeServer.cpp | 60 ++++++++++++++++++- assignment-client/src/octree/OctreeServer.h | 1 + .../entities/src/EntityScriptingInterface.cpp | 10 ++++ .../entities/src/EntityScriptingInterface.h | 14 +++++ .../src/UsersScriptingInterface.cpp | 5 +- .../src/UsersScriptingInterface.h | 9 --- 6 files changed, 85 insertions(+), 14 deletions(-) diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index af5f2c904e..ee3d0ca0e6 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -928,7 +928,7 @@ void OctreeServer::handleJurisdictionRequestPacket(QSharedPointer message) { if (!_isFinished && !_isShuttingDown) { - // these messages are only allowed to come from the domain server, so make sure that is the case + // these messages are only allowed to come from the domain server or authenticated users, so make sure that is the case auto nodeList = DependencyManager::get(); if (message->getSenderSockAddr() == nodeList->getDomainHandler().getSockAddr()) { // it's far cleaner to load up the new content upon server startup @@ -977,6 +977,64 @@ void OctreeServer::handleOctreeFileReplacement(QSharedPointer m } } +void OctreeServer::handleOctreeFileReplacementFromURL(QString url) { + if (!_isFinished && !_isShuttingDown) { + // This call comes from Interface, so we skip our domain server check + if (!_persistAbsoluteFilePath.isEmpty()) { + // Download from our QString + QUrl modelsURL = QUrl(url, QUrl::StrictMode); + QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); + QNetworkRequest request(modelsURL); + QNetworkReply* reply = networkAccessManager.get(request); + connect(reply, &QNetworkReply::finished, [this, reply, modelsURL]() { + QNetworkReply::NetworkError networkError = reply->error(); + if (networkError == QNetworkReply::NoError) { + QByteArray contents = reply->readAll(); + + // Like above, assume we have compressed data + auto compressedOctree = contents; + QByteArray jsonOctree; + + bool wasCompressed = gunzip(compressedOctree, jsonOctree); + if (!wasCompressed) { + // the source was not compressed, assume we were sent regular JSON data + jsonOctree = compressedOctree; + } + // check the JSON data to verify it is an object + if (QJsonDocument::fromJson(jsonOctree).isObject()) { + if (!wasCompressed) { + // source was not compressed, we compress it before we write it locally + gzip(jsonOctree, compressedOctree); + } + + // write the compressed octree data to a special file + auto replacementFilePath = _persistAbsoluteFilePath.append(OctreePersistThread::REPLACEMENT_FILE_EXTENSION); + QFile replacementFile(replacementFilePath); + if (replacementFile.open(QIODevice::WriteOnly) && replacementFile.write(compressedOctree) != -1) { + // we've now written our replacement file, time to take the server down so it can + // process it when it comes back up + qInfo() << "Wrote octree replacement file to" << replacementFilePath << "- stopping server"; + setFinished(true); + } + else { + qWarning() << "Could not write replacement octree data to file - refusing to process"; + } + } + else { + qDebug() << "Received replacement octree file that is invalid - refusing to process"; + } + } + else { + qDebug() << "Error downloading JSON from specified file"; + } + }); + } + else { + qDebug() << "Cannot perform octree file replacement since current persist file path is not yet known"; + } + } +} + bool OctreeServer::readOptionBool(const QString& optionName, const QJsonObject& settingsSectionObject, bool& result) { result = false; // assume it doesn't exist bool optionAvailable = false; diff --git a/assignment-client/src/octree/OctreeServer.h b/assignment-client/src/octree/OctreeServer.h index 8db8d845de..96eafbc1e4 100644 --- a/assignment-client/src/octree/OctreeServer.h +++ b/assignment-client/src/octree/OctreeServer.h @@ -137,6 +137,7 @@ private slots: void handleOctreeDataNackPacket(QSharedPointer message, SharedNodePointer senderNode); void handleJurisdictionRequestPacket(QSharedPointer message, SharedNodePointer senderNode); void handleOctreeFileReplacement(QSharedPointer message); + void handleOctreeFileReplacementFromURL(QString url); void removeSendThread(); protected: diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index f22631d363..3f639cb17c 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -47,6 +47,8 @@ EntityScriptingInterface::EntityScriptingInterface(bool bidOnSimulationOwnership connect(nodeList.data(), &NodeList::canRezChanged, this, &EntityScriptingInterface::canRezChanged); connect(nodeList.data(), &NodeList::canRezTmpChanged, this, &EntityScriptingInterface::canRezTmpChanged); connect(nodeList.data(), &NodeList::canWriteAssetsChanged, this, &EntityScriptingInterface::canWriteAssetsChanged); + connect(nodeList.data(), &NodeList::canReplaceContentChanged, this, &EntityScriptingInterface::canReplaceDomainContentChanged); + } void EntityScriptingInterface::queueEntityMessage(PacketType packetType, @@ -80,6 +82,11 @@ bool EntityScriptingInterface::canWriteAssets() { return nodeList->getThisNodeCanWriteAssets(); } +bool EntityScriptingInterface::canReplaceDomainContent() { + auto nodeList = DependencyManager::get(); + return nodeList->getThisNodeCanReplaceContent(); +} + void EntityScriptingInterface::setEntityTree(EntityTreePointer elementTree) { if (_entityTree) { disconnect(_entityTree.get(), &EntityTree::addingEntity, this, &EntityScriptingInterface::addingEntity); @@ -1158,6 +1165,9 @@ bool EntityScriptingInterface::actionWorker(const QUuid& entityID, return doTransmit; } +void EntityScriptingInterface::replaceDomainContentSet(const QString url){ + +} QUuid EntityScriptingInterface::addAction(const QString& actionTypeString, const QUuid& entityID, diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 575528fa78..9f0d3f0d03 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -359,6 +359,19 @@ public slots: */ Q_INVOKABLE glm::mat4 getEntityLocalTransform(const QUuid& entityID); + /**jsdoc + * Returns true if the user has permissions to replace domain content sets + * @function Entities.canReplaceDomainContent + * @return {bool} true if the user has permissions to replace domain content sets, false if not + */ + Q_INVOKABLE bool canReplaceDomainContent(); + + /**jsdoc + * TODO: temporary placement for content set calls + */ + Q_INVOKABLE void replaceDomainContentSet(const QString fileURL); + + signals: void collisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision); @@ -366,6 +379,7 @@ signals: void canRezChanged(bool canRez); void canRezTmpChanged(bool canRez); void canWriteAssetsChanged(bool canWriteAssets); + void canReplaceDomainContentChanged(); void mousePressOnEntity(const EntityItemID& entityItemID, const PointerEvent& event); void mouseMoveOnEntity(const EntityItemID& entityItemID, const PointerEvent& event); diff --git a/libraries/script-engine/src/UsersScriptingInterface.cpp b/libraries/script-engine/src/UsersScriptingInterface.cpp index ab8e62040b..0622d67d28 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.cpp +++ b/libraries/script-engine/src/UsersScriptingInterface.cpp @@ -19,7 +19,6 @@ UsersScriptingInterface::UsersScriptingInterface() { connect(nodeList.data(), &LimitedNodeList::canKickChanged, this, &UsersScriptingInterface::canKickChanged); connect(nodeList.data(), &NodeList::ignoreRadiusEnabledChanged, this, &UsersScriptingInterface::ignoreRadiusEnabledChanged); connect(nodeList.data(), &NodeList::usernameFromIDReply, this, &UsersScriptingInterface::usernameFromIDReply); - connect(nodeList.data(), &NodeList::canReplaceContentChanged, this, &UsersScriptingInterface::canReplaceContentChanged); } void UsersScriptingInterface::ignore(const QUuid& nodeID, bool ignoreEnabled) { @@ -94,6 +93,4 @@ bool UsersScriptingInterface::getRequestsDomainListData() { void UsersScriptingInterface::setRequestsDomainListData(bool isRequesting) { DependencyManager::get()->setRequestsDomainListData(isRequesting); } -bool UsersScriptingInterface::getCanReplaceContent() { - return DependencyManager::get()->getThisNodeCanReplaceContent(); -} + diff --git a/libraries/script-engine/src/UsersScriptingInterface.h b/libraries/script-engine/src/UsersScriptingInterface.h index b39293dc0e..8aa6e8ce4d 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.h +++ b/libraries/script-engine/src/UsersScriptingInterface.h @@ -25,8 +25,6 @@ class UsersScriptingInterface : public QObject, public Dependency { Q_PROPERTY(bool canKick READ getCanKick) Q_PROPERTY(bool requestsDomainListData READ getRequestsDomainListData WRITE setRequestsDomainListData) - Q_PROPERTY(bool canReplaceContent READ getCanReplaceContent) - public: UsersScriptingInterface(); @@ -132,12 +130,6 @@ public slots: */ bool getIgnoreRadiusEnabled(); - /**jsdoc - * Returns true if the user has permissions to replace domain content sets - * @function Users.getCanReplaceContent - * @return {bool} true if the user has permissions to replace domain content sets, false if not - */ - bool getCanReplaceContent(); signals: void canKickChanged(bool canKick); @@ -162,7 +154,6 @@ signals: * @param {nodeID} NodeID The session ID of the avatar that has disconnected */ void avatarDisconnected(const QUuid& nodeID); - void canReplaceContentChanged(bool canReplaceContent); private: bool getRequestsDomainListData(); From 4ba9b0812511115ca95103a554adab79c6b78df5 Mon Sep 17 00:00:00 2001 From: Liv Date: Thu, 20 Jul 2017 14:00:51 -0700 Subject: [PATCH 04/54] first attempt at url handling in octree server --- assignment-client/src/octree/OctreeServer.cpp | 3 ++- domain-server/src/DomainServer.cpp | 2 +- libraries/entities/src/EntityScriptingInterface.cpp | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index ee3d0ca0e6..9507f3be3b 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -965,7 +965,8 @@ void OctreeServer::handleOctreeFileReplacement(QSharedPointer m } else { qWarning() << "Could not write replacement octree data to file - refusing to process"; } - } else { + } + else { qDebug() << "Received replacement octree file that is invalid - refusing to process"; } } else { diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index c5171620de..18169aaf67 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -2850,4 +2850,4 @@ void DomainServer::handleOctreeFileReplacement(QByteArray octreeFile) { limitedNodeList->sendPacketList(std::move(octreeFilePacketList), *octreeNode); }); -} +} \ No newline at end of file diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 3f639cb17c..4e9a0e83f5 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -1166,7 +1166,7 @@ bool EntityScriptingInterface::actionWorker(const QUuid& entityID, } void EntityScriptingInterface::replaceDomainContentSet(const QString url){ - + } QUuid EntityScriptingInterface::addAction(const QString& actionTypeString, From 26558da794fbf4f01cf4f24dcef603e333a1f134 Mon Sep 17 00:00:00 2001 From: Liv Date: Thu, 20 Jul 2017 18:07:08 -0700 Subject: [PATCH 05/54] Fix stupid typo that was giving connection refused - now working --- assignment-client/src/octree/OctreeServer.cpp | 8 ++++++-- assignment-client/src/octree/OctreeServer.h | 2 +- libraries/entities/src/EntityScriptingInterface.cpp | 10 ++++++++++ libraries/networking/src/udt/PacketHeaders.cpp | 3 ++- libraries/networking/src/udt/PacketHeaders.h | 1 + 5 files changed, 20 insertions(+), 4 deletions(-) diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 9507f3be3b..64891f96a5 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -978,11 +978,14 @@ void OctreeServer::handleOctreeFileReplacement(QSharedPointer m } } -void OctreeServer::handleOctreeFileReplacementFromURL(QString url) { +// Message->getMessage() contains a QByteArray representation of the URL to download from +void OctreeServer::handleOctreeFileReplacementFromURL(QSharedPointer message) { + qInfo() << "Received request to replace content from a url"; if (!_isFinished && !_isShuttingDown) { // This call comes from Interface, so we skip our domain server check if (!_persistAbsoluteFilePath.isEmpty()) { - // Download from our QString + // Convert message data into our URL + QString url(message->getMessage()); QUrl modelsURL = QUrl(url, QUrl::StrictMode); QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); QNetworkRequest request(modelsURL); @@ -1261,6 +1264,7 @@ void OctreeServer::domainSettingsRequestComplete() { packetReceiver.registerListener(PacketType::OctreeDataNack, this, "handleOctreeDataNackPacket"); packetReceiver.registerListener(PacketType::JurisdictionRequest, this, "handleJurisdictionRequestPacket"); packetReceiver.registerListener(PacketType::OctreeFileReplacement, this, "handleOctreeFileReplacement"); + packetReceiver.registerListener(PacketType::OctreeFileReplacementFromUrl, this, "handleOctreeFileReplacementFromURL"); readConfiguration(); diff --git a/assignment-client/src/octree/OctreeServer.h b/assignment-client/src/octree/OctreeServer.h index 96eafbc1e4..b65eec08ec 100644 --- a/assignment-client/src/octree/OctreeServer.h +++ b/assignment-client/src/octree/OctreeServer.h @@ -137,7 +137,7 @@ private slots: void handleOctreeDataNackPacket(QSharedPointer message, SharedNodePointer senderNode); void handleJurisdictionRequestPacket(QSharedPointer message, SharedNodePointer senderNode); void handleOctreeFileReplacement(QSharedPointer message); - void handleOctreeFileReplacementFromURL(QString url); + void handleOctreeFileReplacementFromURL(QSharedPointer message); void removeSendThread(); protected: diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 4e9a0e83f5..f7b9dd6c26 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -1166,7 +1166,17 @@ bool EntityScriptingInterface::actionWorker(const QUuid& entityID, } void EntityScriptingInterface::replaceDomainContentSet(const QString url){ + QByteArray _url(url.toUtf8()); + auto limitedNodeList = DependencyManager::get(); + limitedNodeList->eachMatchingNode([](const SharedNodePointer& node) { + return node->getType() == NodeType::EntityServer && node->getActiveSocket(); + }, [&_url, limitedNodeList](const SharedNodePointer& octreeNode) { + auto octreeFilePacketList = NLPacketList::create(PacketType::OctreeFileReplacementFromUrl, QByteArray(), true, true); + octreeFilePacketList->write(_url); + qCDebug(entities) << "Attempting to send an octree file url to replace domain content"; + limitedNodeList->sendPacketList(std::move(octreeFilePacketList), *octreeNode); + }); } QUuid EntityScriptingInterface::addAction(const QString& actionTypeString, diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 240697d890..2cacf682f8 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -42,7 +42,8 @@ const QSet NON_SOURCED_PACKETS = QSet() << PacketType::DomainServerRemovedNode << PacketType::UsernameFromIDReply << PacketType::OctreeFileReplacement << PacketType::ReplicatedMicrophoneAudioNoEcho << PacketType::ReplicatedMicrophoneAudioWithEcho << PacketType::ReplicatedInjectAudio << PacketType::ReplicatedSilentAudioFrame - << PacketType::ReplicatedAvatarIdentity << PacketType::ReplicatedKillAvatar << PacketType::ReplicatedBulkAvatarData; + << PacketType::ReplicatedAvatarIdentity << PacketType::ReplicatedKillAvatar << PacketType::ReplicatedBulkAvatarData + << PacketType::OctreeFileReplacementFromUrl; const QHash REPLICATED_PACKET_MAPPING { { PacketType::MicrophoneAudioNoEcho, PacketType::ReplicatedMicrophoneAudioNoEcho }, diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 848bfd97cf..feb4767d2c 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -121,6 +121,7 @@ public: ReplicatedAvatarIdentity, ReplicatedKillAvatar, ReplicatedBulkAvatarData, + OctreeFileReplacementFromUrl, NUM_PACKET_TYPE }; }; From 5ea7fbc62ac795f257289b53277b2ae85411f499 Mon Sep 17 00:00:00 2001 From: Liv Date: Fri, 21 Jul 2017 10:27:30 -0700 Subject: [PATCH 06/54] Add node check on permissions for deletion --- assignment-client/src/octree/OctreeServer.cpp | 85 ++++++++++--------- .../entities/src/EntityScriptingInterface.cpp | 22 ++--- 2 files changed, 56 insertions(+), 51 deletions(-) diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 64891f96a5..48ac795520 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -983,58 +983,61 @@ void OctreeServer::handleOctreeFileReplacementFromURL(QSharedPointergetMessage()); - QUrl modelsURL = QUrl(url, QUrl::StrictMode); - QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); - QNetworkRequest request(modelsURL); - QNetworkReply* reply = networkAccessManager.get(request); - connect(reply, &QNetworkReply::finished, [this, reply, modelsURL]() { - QNetworkReply::NetworkError networkError = reply->error(); - if (networkError == QNetworkReply::NoError) { - QByteArray contents = reply->readAll(); + // but confirm that we have permissions to replace content sets + if (DependencyManager::get()->getThisNodeCanReplaceContent()) { + if (!_persistAbsoluteFilePath.isEmpty()) { + // Convert message data into our URL + QString url(message->getMessage()); + QUrl modelsURL = QUrl(url, QUrl::StrictMode); + QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); + QNetworkRequest request(modelsURL); + QNetworkReply* reply = networkAccessManager.get(request); + connect(reply, &QNetworkReply::finished, [this, reply, modelsURL]() { + QNetworkReply::NetworkError networkError = reply->error(); + if (networkError == QNetworkReply::NoError) { + QByteArray contents = reply->readAll(); - // Like above, assume we have compressed data - auto compressedOctree = contents; - QByteArray jsonOctree; + // Like above, assume we have compressed data + auto compressedOctree = contents; + QByteArray jsonOctree; - bool wasCompressed = gunzip(compressedOctree, jsonOctree); - if (!wasCompressed) { - // the source was not compressed, assume we were sent regular JSON data - jsonOctree = compressedOctree; - } - // check the JSON data to verify it is an object - if (QJsonDocument::fromJson(jsonOctree).isObject()) { + bool wasCompressed = gunzip(compressedOctree, jsonOctree); if (!wasCompressed) { - // source was not compressed, we compress it before we write it locally - gzip(jsonOctree, compressedOctree); + // the source was not compressed, assume we were sent regular JSON data + jsonOctree = compressedOctree; } + // check the JSON data to verify it is an object + if (QJsonDocument::fromJson(jsonOctree).isObject()) { + if (!wasCompressed) { + // source was not compressed, we compress it before we write it locally + gzip(jsonOctree, compressedOctree); + } - // write the compressed octree data to a special file - auto replacementFilePath = _persistAbsoluteFilePath.append(OctreePersistThread::REPLACEMENT_FILE_EXTENSION); - QFile replacementFile(replacementFilePath); - if (replacementFile.open(QIODevice::WriteOnly) && replacementFile.write(compressedOctree) != -1) { - // we've now written our replacement file, time to take the server down so it can - // process it when it comes back up - qInfo() << "Wrote octree replacement file to" << replacementFilePath << "- stopping server"; - setFinished(true); + // write the compressed octree data to a special file + auto replacementFilePath = _persistAbsoluteFilePath.append(OctreePersistThread::REPLACEMENT_FILE_EXTENSION); + QFile replacementFile(replacementFilePath); + if (replacementFile.open(QIODevice::WriteOnly) && replacementFile.write(compressedOctree) != -1) { + // we've now written our replacement file, time to take the server down so it can + // process it when it comes back up + qInfo() << "Wrote octree replacement file to" << replacementFilePath << "- stopping server"; + setFinished(true); + } + else { + qWarning() << "Could not write replacement octree data to file - refusing to process"; + } } else { - qWarning() << "Could not write replacement octree data to file - refusing to process"; + qDebug() << "Received replacement octree file that is invalid - refusing to process"; } } else { - qDebug() << "Received replacement octree file that is invalid - refusing to process"; + qDebug() << "Error downloading JSON from specified file"; } - } - else { - qDebug() << "Error downloading JSON from specified file"; - } - }); - } - else { - qDebug() << "Cannot perform octree file replacement since current persist file path is not yet known"; + }); + } + else { + qDebug() << "Cannot perform octree file replacement since current persist file path is not yet known"; + } } } } diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index f7b9dd6c26..b5bec4ccc4 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -1166,17 +1166,19 @@ bool EntityScriptingInterface::actionWorker(const QUuid& entityID, } void EntityScriptingInterface::replaceDomainContentSet(const QString url){ - QByteArray _url(url.toUtf8()); - auto limitedNodeList = DependencyManager::get(); - limitedNodeList->eachMatchingNode([](const SharedNodePointer& node) { - return node->getType() == NodeType::EntityServer && node->getActiveSocket(); - }, [&_url, limitedNodeList](const SharedNodePointer& octreeNode) { - auto octreeFilePacketList = NLPacketList::create(PacketType::OctreeFileReplacementFromUrl, QByteArray(), true, true); - octreeFilePacketList->write(_url); - qCDebug(entities) << "Attempting to send an octree file url to replace domain content"; + if (DependencyManager::get()->getThisNodeCanReplaceContent()) { + QByteArray _url(url.toUtf8()); + auto limitedNodeList = DependencyManager::get(); + limitedNodeList->eachMatchingNode([](const SharedNodePointer& node) { + return node->getType() == NodeType::EntityServer && node->getActiveSocket(); + }, [&_url, limitedNodeList](const SharedNodePointer& octreeNode) { + auto octreeFilePacketList = NLPacketList::create(PacketType::OctreeFileReplacementFromUrl, QByteArray(), true, true); + octreeFilePacketList->write(_url); + qCDebug(entities) << "Attempting to send an octree file url to replace domain content"; - limitedNodeList->sendPacketList(std::move(octreeFilePacketList), *octreeNode); - }); + limitedNodeList->sendPacketList(std::move(octreeFilePacketList), *octreeNode); + }); + }; } QUuid EntityScriptingInterface::addAction(const QString& actionTypeString, From 76cc83374709f47de2b6a02cf34064de1c66294f Mon Sep 17 00:00:00 2001 From: Liv Date: Fri, 21 Jul 2017 17:44:53 -0700 Subject: [PATCH 07/54] move domain management into a separate API --- assignment-client/src/octree/OctreeServer.cpp | 2 - interface/src/Application.cpp | 4 ++ .../DomainManagementScriptingInterface.cpp | 45 +++++++++++++++++++ .../DomainManagementScriptingInterface.h | 40 +++++++++++++++++ .../entities/src/EntityScriptingInterface.cpp | 23 ---------- .../entities/src/EntityScriptingInterface.h | 13 ------ 6 files changed, 89 insertions(+), 38 deletions(-) create mode 100644 interface/src/scripting/DomainManagementScriptingInterface.cpp create mode 100644 interface/src/scripting/DomainManagementScriptingInterface.h diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 48ac795520..8a1e245f0e 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -984,7 +984,6 @@ void OctreeServer::handleOctreeFileReplacementFromURL(QSharedPointer()->getThisNodeCanReplaceContent()) { if (!_persistAbsoluteFilePath.isEmpty()) { // Convert message data into our URL QString url(message->getMessage()); @@ -1038,7 +1037,6 @@ void OctreeServer::handleOctreeFileReplacementFromURL(QSharedPointer(); DependencyManager::set(); DependencyManager::set(); + DependencyManager::set(); DependencyManager::set(true); DependencyManager::set(); DependencyManager::set(); @@ -2120,6 +2122,7 @@ void Application::initializeUi() { surfaceContext->setContextProperty("Render", _renderEngine->getConfiguration().get()); surfaceContext->setContextProperty("Reticle", getApplicationCompositor().getReticleInterface()); surfaceContext->setContextProperty("Snapshot", DependencyManager::get().data()); + surfaceContext->setContextProperty("DomainManagement", DependencyManager::get().data()); surfaceContext->setContextProperty("ApplicationCompositor", &getApplicationCompositor()); @@ -5744,6 +5747,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("OffscreenFlags", DependencyManager::get()->getFlags()); scriptEngine->registerGlobalObject("Desktop", DependencyManager::get().data()); + scriptEngine->registerGlobalObject("DomainManagement", DependencyManager::get().data()); qScriptRegisterMetaType(scriptEngine, wrapperToScriptValue, wrapperFromScriptValue); qScriptRegisterMetaType(scriptEngine, wrapperToScriptValue, wrapperFromScriptValue); diff --git a/interface/src/scripting/DomainManagementScriptingInterface.cpp b/interface/src/scripting/DomainManagementScriptingInterface.cpp new file mode 100644 index 0000000000..3e56f23db3 --- /dev/null +++ b/interface/src/scripting/DomainManagementScriptingInterface.cpp @@ -0,0 +1,45 @@ +// +// DomainManagementScriptingInterface.cpp +// interface/src/scripting +// +// Created by Liv Erickson on 7/21/17. +// Copyright 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 "DomainManagementScriptingInterface.h" +#include "EntitiesLogging.h" +#include "Application.h" + +DomainManagementScriptingInterface::DomainManagementScriptingInterface() +{ + auto nodeList = DependencyManager::get(); + connect(nodeList.data(), &NodeList::canReplaceContentChanged, this, &DomainManagementScriptingInterface::canReplaceDomainContentChanged); +} + +DomainManagementScriptingInterface::~DomainManagementScriptingInterface() { + auto nodeList = DependencyManager::get(); + disconnect(nodeList.data(), &NodeList::canReplaceContentChanged, this, &DomainManagementScriptingInterface::canReplaceDomainContentChanged); +} + +bool DomainManagementScriptingInterface::canReplaceDomainContent() { + auto nodeList = DependencyManager::get(); + return nodeList->getThisNodeCanReplaceContent(); +} + +void DomainManagementScriptingInterface::replaceDomainContentSet(const QString url){ + if (DependencyManager::get()->getThisNodeCanReplaceContent()) { + QByteArray _url(url.toUtf8()); + auto limitedNodeList = DependencyManager::get(); + limitedNodeList->eachMatchingNode([](const SharedNodePointer& node) { + return node->getType() == NodeType::EntityServer && node->getActiveSocket(); + }, [&_url, limitedNodeList](const SharedNodePointer& octreeNode) { + auto octreeFilePacketList = NLPacketList::create(PacketType::OctreeFileReplacementFromUrl, QByteArray(), true, true); + octreeFilePacketList->write(_url); + qCDebug(entities) << "Attempting to send an octree file url to replace domain content"; + + limitedNodeList->sendPacketList(std::move(octreeFilePacketList), *octreeNode); + }); + }; +} diff --git a/interface/src/scripting/DomainManagementScriptingInterface.h b/interface/src/scripting/DomainManagementScriptingInterface.h new file mode 100644 index 0000000000..9723857e5f --- /dev/null +++ b/interface/src/scripting/DomainManagementScriptingInterface.h @@ -0,0 +1,40 @@ +// +// DomainManagementScriptingInterface.h +// interface/src/scripting +// +// Created by Liv Erickson on 7/21/17. +// Copyright 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_DomainManagementScriptingInterface_h +#define hifi_DomainManagementScriptingInterface_h + +#include +#include +#include +#include +#include +#include +#include + +#include "BaseScriptEngine.h" + + +class DomainManagementScriptingInterface : public QObject, public Dependency { +Q_OBJECT +public: + DomainManagementScriptingInterface(); + ~DomainManagementScriptingInterface(); + + +public slots: + Q_INVOKABLE bool canReplaceDomainContent(); + Q_INVOKABLE void replaceDomainContentSet(const QString fileURL); + +signals: + void canReplaceDomainContentChanged(bool canReplaceDomainContent); +}; + +#endif //hifi_DomainManagementScriptingInterface_h \ No newline at end of file diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index b5bec4ccc4..76ff61e2a9 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -47,8 +47,6 @@ EntityScriptingInterface::EntityScriptingInterface(bool bidOnSimulationOwnership connect(nodeList.data(), &NodeList::canRezChanged, this, &EntityScriptingInterface::canRezChanged); connect(nodeList.data(), &NodeList::canRezTmpChanged, this, &EntityScriptingInterface::canRezTmpChanged); connect(nodeList.data(), &NodeList::canWriteAssetsChanged, this, &EntityScriptingInterface::canWriteAssetsChanged); - connect(nodeList.data(), &NodeList::canReplaceContentChanged, this, &EntityScriptingInterface::canReplaceDomainContentChanged); - } void EntityScriptingInterface::queueEntityMessage(PacketType packetType, @@ -82,11 +80,6 @@ bool EntityScriptingInterface::canWriteAssets() { return nodeList->getThisNodeCanWriteAssets(); } -bool EntityScriptingInterface::canReplaceDomainContent() { - auto nodeList = DependencyManager::get(); - return nodeList->getThisNodeCanReplaceContent(); -} - void EntityScriptingInterface::setEntityTree(EntityTreePointer elementTree) { if (_entityTree) { disconnect(_entityTree.get(), &EntityTree::addingEntity, this, &EntityScriptingInterface::addingEntity); @@ -1165,22 +1158,6 @@ bool EntityScriptingInterface::actionWorker(const QUuid& entityID, return doTransmit; } -void EntityScriptingInterface::replaceDomainContentSet(const QString url){ - if (DependencyManager::get()->getThisNodeCanReplaceContent()) { - QByteArray _url(url.toUtf8()); - auto limitedNodeList = DependencyManager::get(); - limitedNodeList->eachMatchingNode([](const SharedNodePointer& node) { - return node->getType() == NodeType::EntityServer && node->getActiveSocket(); - }, [&_url, limitedNodeList](const SharedNodePointer& octreeNode) { - auto octreeFilePacketList = NLPacketList::create(PacketType::OctreeFileReplacementFromUrl, QByteArray(), true, true); - octreeFilePacketList->write(_url); - qCDebug(entities) << "Attempting to send an octree file url to replace domain content"; - - limitedNodeList->sendPacketList(std::move(octreeFilePacketList), *octreeNode); - }); - }; -} - QUuid EntityScriptingInterface::addAction(const QString& actionTypeString, const QUuid& entityID, const QVariantMap& arguments) { diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 9f0d3f0d03..1b61ac2b61 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -359,18 +359,6 @@ public slots: */ Q_INVOKABLE glm::mat4 getEntityLocalTransform(const QUuid& entityID); - /**jsdoc - * Returns true if the user has permissions to replace domain content sets - * @function Entities.canReplaceDomainContent - * @return {bool} true if the user has permissions to replace domain content sets, false if not - */ - Q_INVOKABLE bool canReplaceDomainContent(); - - /**jsdoc - * TODO: temporary placement for content set calls - */ - Q_INVOKABLE void replaceDomainContentSet(const QString fileURL); - signals: void collisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision); @@ -379,7 +367,6 @@ signals: void canRezChanged(bool canRez); void canRezTmpChanged(bool canRez); void canWriteAssetsChanged(bool canWriteAssets); - void canReplaceDomainContentChanged(); void mousePressOnEntity(const EntityItemID& entityItemID, const PointerEvent& event); void mouseMoveOnEntity(const EntityItemID& entityItemID, const PointerEvent& event); From 32ddffd9c8e9b30d217963c0a7da8775e743071a Mon Sep 17 00:00:00 2001 From: Liv Date: Mon, 24 Jul 2017 18:09:32 -0700 Subject: [PATCH 08/54] Move logic for confirmation into Application.cpp for handling files directly --- interface/src/Application.cpp | 42 +++++++++++++++++-- interface/src/Application.h | 4 ++ .../DomainManagementScriptingInterface.cpp | 15 +------ .../DomainManagementScriptingInterface.h | 4 +- 4 files changed, 48 insertions(+), 17 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8935d9c477..f8153ff980 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -222,6 +222,7 @@ static const int MIN_PROCESSING_THREAD_POOL_SIZE = 1; static const QString SNAPSHOT_EXTENSION = ".jpg"; static const QString SVO_EXTENSION = ".svo"; static const QString SVO_JSON_EXTENSION = ".svo.json"; +static const QString JSON_GZ_EXTENSION = ".json.gz"; static const QString JSON_EXTENSION = ".json"; static const QString JS_EXTENSION = ".js"; static const QString FST_EXTENSION = ".fst"; @@ -254,13 +255,14 @@ static const QString DESKTOP_DISPLAY_PLUGIN_NAME = "Desktop"; static const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system"; -const QHash Application::_acceptedExtensions { +const QHash Application::_acceptedExtensions{ { SVO_EXTENSION, &Application::importSVOFromURL }, { SVO_JSON_EXTENSION, &Application::importSVOFromURL }, { AVA_JSON_EXTENSION, &Application::askToWearAvatarAttachmentUrl }, { JSON_EXTENSION, &Application::importJSONFromURL }, { JS_EXTENSION, &Application::askToLoadScript }, - { FST_EXTENSION, &Application::askToSetAvatarUrl } + { FST_EXTENSION, &Application::askToSetAvatarUrl }, + { JSON_GZ_EXTENSION, &Application::askToReplaceDomainContent } }; class DeadlockWatchdogThread : public QThread { @@ -2724,7 +2726,6 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { bool Application::importJSONFromURL(const QString& urlString) { // we only load files that terminate in just .json (not .svo.json and not .ava.json) // if they come from the High Fidelity Marketplace Assets CDN - QUrl jsonURL { urlString }; if (jsonURL.host().endsWith(MARKETPLACE_CDN_HOSTNAME)) { @@ -6036,6 +6037,41 @@ bool Application::askToWearAvatarAttachmentUrl(const QString& url) { return true; } +bool Application::askToReplaceDomainContent(const QString& url) { + + if (DependencyManager::get()->getThisNodeCanReplaceContent()) { + // Create a confirmation dialog when this call is made + static const QString infoText = "Your domain's content will be replaced but backup files of your " + "domain's content will not immediately be changed.\n Save a manual backup of your" + "models.json.gz file, usually stored at:\n" + "C:/Users/[username]/AppData/Roaming/High Fidelity/assignment-client/entities/models.json.gz"; + + bool agreeToReplaceContent = false; // assume false + agreeToReplaceContent = QMessageBox::Yes == OffscreenUi::question("Are you sure you want to replace this domain's content set?", + infoText, QMessageBox::Yes | QMessageBox::No, QMessageBox::No); + + if (agreeToReplaceContent) { + // Given confirmation, send request to domain server to replace content + QByteArray _url(url.toUtf8()); + auto limitedNodeList = DependencyManager::get(); + limitedNodeList->eachMatchingNode([](const SharedNodePointer& node) { + return node->getType() == NodeType::EntityServer && node->getActiveSocket(); + }, [&_url, limitedNodeList](const SharedNodePointer& octreeNode) { + auto octreeFilePacketList = NLPacketList::create(PacketType::OctreeFileReplacementFromUrl, QByteArray(), true, true); + octreeFilePacketList->write(_url); + qCDebug(entities) << "Attempting to send an octree file url to replace domain content"; + + limitedNodeList->sendPacketList(std::move(octreeFilePacketList), *octreeNode); + return true; + }); + } + } else { + OffscreenUi::warning("Unable to replace content", "You do not have permissions to replace domain content", QMessageBox::Ok, QMessageBox::Ok); + } + return false; + +} + void Application::displayAvatarAttachmentWarning(const QString& message) const { auto avatarAttachmentWarningTitle = tr("Avatar Attachment Failure"); OffscreenUi::warning(avatarAttachmentWarningTitle, message); diff --git a/interface/src/Application.h b/interface/src/Application.h index ce27c4a70a..a8467b5b1e 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -311,6 +311,8 @@ signals: void uploadRequest(QString path); void receivedHifiSchemeURL(const QString& url); + void requestDomainContentReplacement(const QString& url); + public slots: QVector pasteEntities(float x, float y, float z); bool exportEntities(const QString& filename, const QVector& entityIDs, const glm::vec3* givenOffset = nullptr); @@ -426,6 +428,8 @@ private slots: void displayAvatarAttachmentWarning(const QString& message) const; bool displayAvatarAttachmentConfirmationDialog(const QString& name) const; + bool askToReplaceDomainContent(const QString& url); + void setSessionUUID(const QUuid& sessionUUID) const; void domainChanged(const QString& domainHostname); diff --git a/interface/src/scripting/DomainManagementScriptingInterface.cpp b/interface/src/scripting/DomainManagementScriptingInterface.cpp index 3e56f23db3..3b05b2d905 100644 --- a/interface/src/scripting/DomainManagementScriptingInterface.cpp +++ b/interface/src/scripting/DomainManagementScriptingInterface.cpp @@ -11,6 +11,7 @@ #include "DomainManagementScriptingInterface.h" #include "EntitiesLogging.h" #include "Application.h" +#include "OffscreenUi.h" DomainManagementScriptingInterface::DomainManagementScriptingInterface() { @@ -28,18 +29,6 @@ bool DomainManagementScriptingInterface::canReplaceDomainContent() { return nodeList->getThisNodeCanReplaceContent(); } -void DomainManagementScriptingInterface::replaceDomainContentSet(const QString url){ - if (DependencyManager::get()->getThisNodeCanReplaceContent()) { - QByteArray _url(url.toUtf8()); - auto limitedNodeList = DependencyManager::get(); - limitedNodeList->eachMatchingNode([](const SharedNodePointer& node) { - return node->getType() == NodeType::EntityServer && node->getActiveSocket(); - }, [&_url, limitedNodeList](const SharedNodePointer& octreeNode) { - auto octreeFilePacketList = NLPacketList::create(PacketType::OctreeFileReplacementFromUrl, QByteArray(), true, true); - octreeFilePacketList->write(_url); - qCDebug(entities) << "Attempting to send an octree file url to replace domain content"; +void DomainManagementScriptingInterface::replaceDomainContentSet(const QString& url){ - limitedNodeList->sendPacketList(std::move(octreeFilePacketList), *octreeNode); - }); - }; } diff --git a/interface/src/scripting/DomainManagementScriptingInterface.h b/interface/src/scripting/DomainManagementScriptingInterface.h index 9723857e5f..ded0f843d7 100644 --- a/interface/src/scripting/DomainManagementScriptingInterface.h +++ b/interface/src/scripting/DomainManagementScriptingInterface.h @@ -31,7 +31,9 @@ public: public slots: Q_INVOKABLE bool canReplaceDomainContent(); - Q_INVOKABLE void replaceDomainContentSet(const QString fileURL); + +protected: + void replaceDomainContentSet(const QString& fileURL); signals: void canReplaceDomainContentChanged(bool canReplaceDomainContent); From 89a1c7a69746c125ffb23b40c54f8076a8d0879f Mon Sep 17 00:00:00 2001 From: Liv Date: Tue, 25 Jul 2017 11:24:57 -0700 Subject: [PATCH 09/54] code cleanup --- interface/src/Application.cpp | 14 +++++++------- .../DomainManagementScriptingInterface.cpp | 5 ----- .../scripting/DomainManagementScriptingInterface.h | 3 --- 3 files changed, 7 insertions(+), 15 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f8153ff980..32e69366ae 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6041,10 +6041,11 @@ bool Application::askToReplaceDomainContent(const QString& url) { if (DependencyManager::get()->getThisNodeCanReplaceContent()) { // Create a confirmation dialog when this call is made - static const QString infoText = "Your domain's content will be replaced but backup files of your " - "domain's content will not immediately be changed.\n Save a manual backup of your" - "models.json.gz file, usually stored at:\n" - "C:/Users/[username]/AppData/Roaming/High Fidelity/assignment-client/entities/models.json.gz"; + const int MAX_CHARACTERS_PER_LINE = 90; + static const QString infoText = simpleWordWrap("Your domain's content will be replaced but backup files of your " + "domain's content will not immediately be changed. Save a manual backup of your" + "models.json.gz file, usually stored at:", MAX_CHARACTERS_PER_LINE) + + "\nC:/Users/[username]/AppData/Roaming/High Fidelity/assignment-client/entities/models.json.gz"; bool agreeToReplaceContent = false; // assume false agreeToReplaceContent = QMessageBox::Yes == OffscreenUi::question("Are you sure you want to replace this domain's content set?", @@ -6052,15 +6053,14 @@ bool Application::askToReplaceDomainContent(const QString& url) { if (agreeToReplaceContent) { // Given confirmation, send request to domain server to replace content + qCDebug(interfaceapp) << "Attempting to replace domain content: " << url; QByteArray _url(url.toUtf8()); auto limitedNodeList = DependencyManager::get(); limitedNodeList->eachMatchingNode([](const SharedNodePointer& node) { return node->getType() == NodeType::EntityServer && node->getActiveSocket(); }, [&_url, limitedNodeList](const SharedNodePointer& octreeNode) { auto octreeFilePacketList = NLPacketList::create(PacketType::OctreeFileReplacementFromUrl, QByteArray(), true, true); - octreeFilePacketList->write(_url); - qCDebug(entities) << "Attempting to send an octree file url to replace domain content"; - + octreeFilePacketList->write(_url); limitedNodeList->sendPacketList(std::move(octreeFilePacketList), *octreeNode); return true; }); diff --git a/interface/src/scripting/DomainManagementScriptingInterface.cpp b/interface/src/scripting/DomainManagementScriptingInterface.cpp index 3b05b2d905..593fedad3c 100644 --- a/interface/src/scripting/DomainManagementScriptingInterface.cpp +++ b/interface/src/scripting/DomainManagementScriptingInterface.cpp @@ -9,7 +9,6 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include "DomainManagementScriptingInterface.h" -#include "EntitiesLogging.h" #include "Application.h" #include "OffscreenUi.h" @@ -28,7 +27,3 @@ bool DomainManagementScriptingInterface::canReplaceDomainContent() { auto nodeList = DependencyManager::get(); return nodeList->getThisNodeCanReplaceContent(); } - -void DomainManagementScriptingInterface::replaceDomainContentSet(const QString& url){ - -} diff --git a/interface/src/scripting/DomainManagementScriptingInterface.h b/interface/src/scripting/DomainManagementScriptingInterface.h index ded0f843d7..85955254c7 100644 --- a/interface/src/scripting/DomainManagementScriptingInterface.h +++ b/interface/src/scripting/DomainManagementScriptingInterface.h @@ -32,9 +32,6 @@ public: public slots: Q_INVOKABLE bool canReplaceDomainContent(); -protected: - void replaceDomainContentSet(const QString& fileURL); - signals: void canReplaceDomainContentChanged(bool canReplaceDomainContent); }; From 2377e4a5dbd09852b51502a632ab376a76258f59 Mon Sep 17 00:00:00 2001 From: Liv Date: Tue, 25 Jul 2017 11:32:02 -0700 Subject: [PATCH 10/54] fix message formatting --- interface/src/Application.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 32e69366ae..2ce7faab5d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6042,8 +6042,7 @@ bool Application::askToReplaceDomainContent(const QString& url) { if (DependencyManager::get()->getThisNodeCanReplaceContent()) { // Create a confirmation dialog when this call is made const int MAX_CHARACTERS_PER_LINE = 90; - static const QString infoText = simpleWordWrap("Your domain's content will be replaced but backup files of your " - "domain's content will not immediately be changed. Save a manual backup of your" + static const QString infoText = simpleWordWrap("Your domain's content will be replaced but backup files will not immediately be changed. Save a manual backup of your" "models.json.gz file, usually stored at:", MAX_CHARACTERS_PER_LINE) + "\nC:/Users/[username]/AppData/Roaming/High Fidelity/assignment-client/entities/models.json.gz"; From 57b27a7bb756a661fa3b207383810c551dac8de3 Mon Sep 17 00:00:00 2001 From: Liv Date: Tue, 25 Jul 2017 20:17:20 -0700 Subject: [PATCH 11/54] change packet type to be sourced, change from packet list to single packet --- assignment-client/src/octree/OctreeServer.cpp | 19 ++++++++----------- interface/src/Application.cpp | 8 ++++---- interface/src/Application.h | 2 -- .../networking/src/udt/PacketHeaders.cpp | 3 +-- 4 files changed, 13 insertions(+), 19 deletions(-) diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 8a1e245f0e..d6a0cc7b92 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -928,7 +928,7 @@ void OctreeServer::handleJurisdictionRequestPacket(QSharedPointer message) { if (!_isFinished && !_isShuttingDown) { - // these messages are only allowed to come from the domain server or authenticated users, so make sure that is the case + // these messages are only allowed to come from the domain server, so make sure that is the case auto nodeList = DependencyManager::get(); if (message->getSenderSockAddr() == nodeList->getDomainHandler().getSockAddr()) { // it's far cleaner to load up the new content upon server startup @@ -965,8 +965,7 @@ void OctreeServer::handleOctreeFileReplacement(QSharedPointer m } else { qWarning() << "Could not write replacement octree data to file - refusing to process"; } - } - else { + } else { qDebug() << "Received replacement octree file that is invalid - refusing to process"; } } else { @@ -984,6 +983,7 @@ void OctreeServer::handleOctreeFileReplacementFromURL(QSharedPointer()->getThisNodeCanReplaceContent()) { if (!_persistAbsoluteFilePath.isEmpty()) { // Convert message data into our URL QString url(message->getMessage()); @@ -1020,23 +1020,20 @@ void OctreeServer::handleOctreeFileReplacementFromURL(QSharedPointer Application::_acceptedExtensions{ +const QHash Application::_acceptedExtensions { { SVO_EXTENSION, &Application::importSVOFromURL }, { SVO_JSON_EXTENSION, &Application::importSVOFromURL }, { AVA_JSON_EXTENSION, &Application::askToWearAvatarAttachmentUrl }, @@ -6070,9 +6070,9 @@ bool Application::askToReplaceDomainContent(const QString& url) { limitedNodeList->eachMatchingNode([](const SharedNodePointer& node) { return node->getType() == NodeType::EntityServer && node->getActiveSocket(); }, [&_url, limitedNodeList](const SharedNodePointer& octreeNode) { - auto octreeFilePacketList = NLPacketList::create(PacketType::OctreeFileReplacementFromUrl, QByteArray(), true, true); - octreeFilePacketList->write(_url); - limitedNodeList->sendPacketList(std::move(octreeFilePacketList), *octreeNode); + auto octreeFilePacket = NLPacket::create(PacketType::OctreeFileReplacementFromUrl, _url.size(), true); + octreeFilePacket->write(_url); + limitedNodeList->sendPacket(std::move(octreeFilePacket), *octreeNode); return true; }); } diff --git a/interface/src/Application.h b/interface/src/Application.h index a8467b5b1e..913fbebb15 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -311,8 +311,6 @@ signals: void uploadRequest(QString path); void receivedHifiSchemeURL(const QString& url); - void requestDomainContentReplacement(const QString& url); - public slots: QVector pasteEntities(float x, float y, float z); bool exportEntities(const QString& filename, const QVector& entityIDs, const glm::vec3* givenOffset = nullptr); diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 2cacf682f8..240697d890 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -42,8 +42,7 @@ const QSet NON_SOURCED_PACKETS = QSet() << PacketType::DomainServerRemovedNode << PacketType::UsernameFromIDReply << PacketType::OctreeFileReplacement << PacketType::ReplicatedMicrophoneAudioNoEcho << PacketType::ReplicatedMicrophoneAudioWithEcho << PacketType::ReplicatedInjectAudio << PacketType::ReplicatedSilentAudioFrame - << PacketType::ReplicatedAvatarIdentity << PacketType::ReplicatedKillAvatar << PacketType::ReplicatedBulkAvatarData - << PacketType::OctreeFileReplacementFromUrl; + << PacketType::ReplicatedAvatarIdentity << PacketType::ReplicatedKillAvatar << PacketType::ReplicatedBulkAvatarData; const QHash REPLICATED_PACKET_MAPPING { { PacketType::MicrophoneAudioNoEcho, PacketType::ReplicatedMicrophoneAudioNoEcho }, From eb1b7e52dfebd28da8ab8c476f43816863d7c87a Mon Sep 17 00:00:00 2001 From: Liv Date: Wed, 26 Jul 2017 09:00:51 -0700 Subject: [PATCH 12/54] restore original files that had erroneous whitespace changes to reduce diff --- domain-server/src/DomainServer.cpp | 6 ++---- libraries/entities/src/EntityScriptingInterface.cpp | 1 + libraries/entities/src/EntityScriptingInterface.h | 1 - libraries/script-engine/src/UsersScriptingInterface.cpp | 1 - libraries/script-engine/src/UsersScriptingInterface.h | 2 +- 5 files changed, 4 insertions(+), 7 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 18169aaf67..163bd48f1b 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -160,9 +160,7 @@ DomainServer::DomainServer(int argc, char* argv[]) : getTemporaryName(); } - _gatekeeper.preloadAllowedUserPublicKeys(); // so they can connect on first request - - //send signal to DomainMetadata when descriptors changed + // send signal to DomainMetadata when descriptors changed _metadata = new DomainMetadata(this); connect(&_settingsManager, &DomainServerSettingsManager::settingsUpdated, _metadata, &DomainMetadata::descriptorsChanged); @@ -2850,4 +2848,4 @@ void DomainServer::handleOctreeFileReplacement(QByteArray octreeFile) { limitedNodeList->sendPacketList(std::move(octreeFilePacketList), *octreeNode); }); -} \ No newline at end of file +} diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 9407adb618..9d2cb30c6e 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -1164,6 +1164,7 @@ bool EntityScriptingInterface::actionWorker(const QUuid& entityID, return doTransmit; } + QUuid EntityScriptingInterface::addAction(const QString& actionTypeString, const QUuid& entityID, const QVariantMap& arguments) { diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 1b61ac2b61..575528fa78 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -359,7 +359,6 @@ public slots: */ Q_INVOKABLE glm::mat4 getEntityLocalTransform(const QUuid& entityID); - signals: void collisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision); diff --git a/libraries/script-engine/src/UsersScriptingInterface.cpp b/libraries/script-engine/src/UsersScriptingInterface.cpp index 0622d67d28..6dc3188b3f 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.cpp +++ b/libraries/script-engine/src/UsersScriptingInterface.cpp @@ -93,4 +93,3 @@ bool UsersScriptingInterface::getRequestsDomainListData() { void UsersScriptingInterface::setRequestsDomainListData(bool isRequesting) { DependencyManager::get()->setRequestsDomainListData(isRequesting); } - diff --git a/libraries/script-engine/src/UsersScriptingInterface.h b/libraries/script-engine/src/UsersScriptingInterface.h index 8aa6e8ce4d..acaa92d9c8 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.h +++ b/libraries/script-engine/src/UsersScriptingInterface.h @@ -25,6 +25,7 @@ class UsersScriptingInterface : public QObject, public Dependency { Q_PROPERTY(bool canKick READ getCanKick) Q_PROPERTY(bool requestsDomainListData READ getRequestsDomainListData WRITE setRequestsDomainListData) + public: UsersScriptingInterface(); @@ -130,7 +131,6 @@ public slots: */ bool getIgnoreRadiusEnabled(); - signals: void canKickChanged(bool canKick); void ignoreRadiusEnabledChanged(bool isEnabled); From 63d637c4db67e3300f849fc3b4a5acbce81478e1 Mon Sep 17 00:00:00 2001 From: Liv Date: Wed, 26 Jul 2017 10:02:21 -0700 Subject: [PATCH 13/54] Add line to move user back to origin to be near new content --- interface/src/Application.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 912be83b24..78f5ad04ad 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -255,6 +255,8 @@ static const QString DESKTOP_DISPLAY_PLUGIN_NAME = "Desktop"; static const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system"; +static const QString DOMAIN_ORIGIN = "/0, 0, 0"; + const QHash Application::_acceptedExtensions { { SVO_EXTENSION, &Application::importSVOFromURL }, { SVO_JSON_EXTENSION, &Application::importSVOFromURL }, @@ -6075,6 +6077,8 @@ bool Application::askToReplaceDomainContent(const QString& url) { limitedNodeList->sendPacket(std::move(octreeFilePacket), *octreeNode); return true; }); + DependencyManager::get()->handleLookupString(DOMAIN_ORIGIN); + } } else { OffscreenUi::warning("Unable to replace content", "You do not have permissions to replace domain content", QMessageBox::Ok, QMessageBox::Ok); From be860d6c870421c54afd6e0dda624610631ebfe4 Mon Sep 17 00:00:00 2001 From: Liv Date: Wed, 26 Jul 2017 10:20:29 -0700 Subject: [PATCH 14/54] small string fix --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 78f5ad04ad..1e1eae3bbc 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6056,7 +6056,7 @@ bool Application::askToReplaceDomainContent(const QString& url) { if (DependencyManager::get()->getThisNodeCanReplaceContent()) { // Create a confirmation dialog when this call is made const int MAX_CHARACTERS_PER_LINE = 90; - static const QString infoText = simpleWordWrap("Your domain's content will be replaced but backup files will not immediately be changed. Save a manual backup of your" + static const QString infoText = simpleWordWrap("Your domain's content will be replaced, but backup files will not immediately be changed. Save a manual backup of your" "models.json.gz file, usually stored at:", MAX_CHARACTERS_PER_LINE) + "\nC:/Users/[username]/AppData/Roaming/High Fidelity/assignment-client/entities/models.json.gz"; From 9ec14057f01a67f98fa9bb27bdef3dcddec8d9b3 Mon Sep 17 00:00:00 2001 From: Menithal Date: Sat, 29 Jul 2017 21:51:19 +0300 Subject: [PATCH 15/54] Opened up setForceFaceTrackerConnected --- libraries/avatars/src/AvatarData.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 16768ec62a..c41b53cb45 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -547,7 +547,7 @@ public: Q_INVOKABLE void updateAvatarEntity(const QUuid& entityID, const QByteArray& entityData); Q_INVOKABLE void clearAvatarEntity(const QUuid& entityID); - void setForceFaceTrackerConnected(bool connected) { _forceFaceTrackerConnected = connected; } + Q_INVOKABLE void setForceFaceTrackerConnected(bool connected) { _forceFaceTrackerConnected = connected; } // key state void setKeyState(KeyState s) { _keyState = s; } From d2abc42e8f93a36f13e0092496966ffeeb4857c8 Mon Sep 17 00:00:00 2001 From: Liv Date: Mon, 7 Aug 2017 12:43:54 -0700 Subject: [PATCH 16/54] Update domain server to include permissions --- domain-server/src/DomainServerSettingsManager.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index dbc6e45b28..b9e28f85b4 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -295,6 +295,12 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList // persist the new config so the user config file has the correctly merged config persistToFile(); } + + if (oldVersion < 1.8) { + // This was prior to addition of domain content replacement, add that to localhost permissions by default + _standardAgentPermissions[NodePermissions::standardNameLocalhost]->set(NodePermissions::Permission::canReplaceDomainContent); + packPermissions(); + } } unpackPermissions(); From b63fcc329e02f4c3618987f9934df2daf4dc610a Mon Sep 17 00:00:00 2001 From: Liv Date: Mon, 7 Aug 2017 17:28:49 -0700 Subject: [PATCH 17/54] localhost default can change settings --- domain-server/src/DomainServerSettingsManager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index b9e28f85b4..d93126f2c7 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -297,6 +297,7 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList } if (oldVersion < 1.8) { + unpackPermissions(); // This was prior to addition of domain content replacement, add that to localhost permissions by default _standardAgentPermissions[NodePermissions::standardNameLocalhost]->set(NodePermissions::Permission::canReplaceDomainContent); packPermissions(); From 3f301622159eb887e26f7db3cd61d203c9b632f4 Mon Sep 17 00:00:00 2001 From: Liv Date: Tue, 8 Aug 2017 09:44:36 -0700 Subject: [PATCH 18/54] Make spawning point not 0,0,0 and change error message --- interface/src/Application.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d1d92addf6..4e732dad89 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -257,7 +257,7 @@ static const QString DESKTOP_DISPLAY_PLUGIN_NAME = "Desktop"; static const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system"; -static const QString DOMAIN_ORIGIN = "/0, 0, 0"; +static const QString DOMAIN_SPAWNING_POINT = "/0, -200, 0"; const QHash Application::_acceptedExtensions { { SVO_EXTENSION, &Application::importSVOFromURL }, @@ -6129,7 +6129,7 @@ bool Application::askToReplaceDomainContent(const QString& url) { if (DependencyManager::get()->getThisNodeCanReplaceContent()) { // Create a confirmation dialog when this call is made const int MAX_CHARACTERS_PER_LINE = 90; - static const QString infoText = simpleWordWrap("Your domain's content will be replaced, but backup files will not immediately be changed. Save a manual backup of your" + static const QString infoText = simpleWordWrap("Your domain's content will be replaced with a new content set. If you want to restore your domain from the current domain content, save a manual backup of your" "models.json.gz file, usually stored at:", MAX_CHARACTERS_PER_LINE) + "\nC:/Users/[username]/AppData/Roaming/High Fidelity/assignment-client/entities/models.json.gz"; @@ -6150,7 +6150,7 @@ bool Application::askToReplaceDomainContent(const QString& url) { limitedNodeList->sendPacket(std::move(octreeFilePacket), *octreeNode); return true; }); - DependencyManager::get()->handleLookupString(DOMAIN_ORIGIN); + DependencyManager::get()->handleLookupString(DOMAIN_SPAWNING_POINT); } } else { From ab8f5c12881a2d67d87178fce036ac4e97375695 Mon Sep 17 00:00:00 2001 From: Liv Date: Tue, 8 Aug 2017 13:55:07 -0700 Subject: [PATCH 19/54] add user logging detail message --- interface/src/Application.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4e732dad89..feb64c8b93 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6125,11 +6125,12 @@ bool Application::askToWearAvatarAttachmentUrl(const QString& url) { } bool Application::askToReplaceDomainContent(const QString& url) { - + QString methodDetails; if (DependencyManager::get()->getThisNodeCanReplaceContent()) { // Create a confirmation dialog when this call is made const int MAX_CHARACTERS_PER_LINE = 90; - static const QString infoText = simpleWordWrap("Your domain's content will be replaced with a new content set. If you want to restore your domain from the current domain content, save a manual backup of your" + static const QString infoText = simpleWordWrap("Your domain's content will be replaced with a new content set." + "If you want to restore your domain from the current domain content, save a manual backup of your" "models.json.gz file, usually stored at:", MAX_CHARACTERS_PER_LINE) + "\nC:/Users/[username]/AppData/Roaming/High Fidelity/assignment-client/entities/models.json.gz"; @@ -6151,11 +6152,20 @@ bool Application::askToReplaceDomainContent(const QString& url) { return true; }); DependencyManager::get()->handleLookupString(DOMAIN_SPAWNING_POINT); - + methodDetails = "SuccessfulRequestToReplaceContent"; + } else { + methodDetails = "UserDeclinedToReplaceContent"; } } else { - OffscreenUi::warning("Unable to replace content", "You do not have permissions to replace domain content", QMessageBox::Ok, QMessageBox::Ok); + methodDetails = "UserDoesNotHavePermissionToReplaceContent"; + OffscreenUi::warning("Unable to replace content", "You do not have permissions to replace domain content", + QMessageBox::Ok, QMessageBox::Ok); } + QJsonObject messageProperties = { + { "status", methodDetails }, + { "content_set_url", url } + }; + UserActivityLogger::getInstance().logAction("replace_domain_content", messageProperties); return false; } From bd1619b1b2a49add36a710492b684c3508dd97d3 Mon Sep 17 00:00:00 2001 From: Liv Date: Wed, 9 Aug 2017 09:14:46 -0700 Subject: [PATCH 20/54] update error message wording --- interface/src/Application.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index feb64c8b93..8a0856348a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6129,10 +6129,9 @@ bool Application::askToReplaceDomainContent(const QString& url) { if (DependencyManager::get()->getThisNodeCanReplaceContent()) { // Create a confirmation dialog when this call is made const int MAX_CHARACTERS_PER_LINE = 90; - static const QString infoText = simpleWordWrap("Your domain's content will be replaced with a new content set." - "If you want to restore your domain from the current domain content, save a manual backup of your" - "models.json.gz file, usually stored at:", MAX_CHARACTERS_PER_LINE) + - "\nC:/Users/[username]/AppData/Roaming/High Fidelity/assignment-client/entities/models.json.gz"; + static const QString infoText = simpleWordWrap("Your domain's content will be replaced with a new content set. " + "If you want to save what you have now, create a backup bfore proceeding.For more information about backing up " + "and restoring content, visit the documentation page at .", MAX_CHARACTERS_PER_LINE); bool agreeToReplaceContent = false; // assume false agreeToReplaceContent = QMessageBox::Yes == OffscreenUi::question("Are you sure you want to replace this domain's content set?", From 07846864506642cc150f9374f2801c523459881e Mon Sep 17 00:00:00 2001 From: Liv Date: Wed, 9 Aug 2017 10:17:31 -0700 Subject: [PATCH 21/54] small typo fix --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8a0856348a..0f0ab9362d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6130,7 +6130,7 @@ bool Application::askToReplaceDomainContent(const QString& url) { // Create a confirmation dialog when this call is made const int MAX_CHARACTERS_PER_LINE = 90; static const QString infoText = simpleWordWrap("Your domain's content will be replaced with a new content set. " - "If you want to save what you have now, create a backup bfore proceeding.For more information about backing up " + "If you want to save what you have now, create a backup before proceeding. For more information about backing up " "and restoring content, visit the documentation page at .", MAX_CHARACTERS_PER_LINE); bool agreeToReplaceContent = false; // assume false From 6bde4db0d7fa845b7019bdc781c13682ad072628 Mon Sep 17 00:00:00 2001 From: Liv Date: Wed, 9 Aug 2017 16:35:25 -0700 Subject: [PATCH 22/54] wrap in marketplace check and change landing point --- interface/src/Application.cpp | 63 +++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0f0ab9362d..103d8f50c3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -257,7 +257,7 @@ static const QString DESKTOP_DISPLAY_PLUGIN_NAME = "Desktop"; static const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system"; -static const QString DOMAIN_SPAWNING_POINT = "/0, -200, 0"; +static const QString DOMAIN_SPAWNING_POINT = "/0, -10, 0"; const QHash Application::_acceptedExtensions { { SVO_EXTENSION, &Application::importSVOFromURL }, @@ -6127,38 +6127,44 @@ bool Application::askToWearAvatarAttachmentUrl(const QString& url) { bool Application::askToReplaceDomainContent(const QString& url) { QString methodDetails; if (DependencyManager::get()->getThisNodeCanReplaceContent()) { - // Create a confirmation dialog when this call is made - const int MAX_CHARACTERS_PER_LINE = 90; - static const QString infoText = simpleWordWrap("Your domain's content will be replaced with a new content set. " - "If you want to save what you have now, create a backup before proceeding. For more information about backing up " - "and restoring content, visit the documentation page at .", MAX_CHARACTERS_PER_LINE); + QUrl originURL{ url }; + if (originURL.host().endsWith(MARKETPLACE_CDN_HOSTNAME)) { + // Create a confirmation dialog when this call is made + const int MAX_CHARACTERS_PER_LINE = 90; + static const QString infoText = simpleWordWrap("Your domain's content will be replaced with a new content set. " + "If you want to save what you have now, create a backup before proceeding. For more information about backing up " + "and restoring content, visit the documentation page at: ", MAX_CHARACTERS_PER_LINE) + + "\nhttps://docs.highfidelity.com/create-and-explore/start-working-in-your-sandbox/restoring-sandbox-content"; - bool agreeToReplaceContent = false; // assume false - agreeToReplaceContent = QMessageBox::Yes == OffscreenUi::question("Are you sure you want to replace this domain's content set?", - infoText, QMessageBox::Yes | QMessageBox::No, QMessageBox::No); + bool agreeToReplaceContent = false; // assume false + agreeToReplaceContent = QMessageBox::Yes == OffscreenUi::question("Are you sure you want to replace this domain's content set?", + infoText, QMessageBox::Yes | QMessageBox::No, QMessageBox::No); - if (agreeToReplaceContent) { - // Given confirmation, send request to domain server to replace content - qCDebug(interfaceapp) << "Attempting to replace domain content: " << url; - QByteArray _url(url.toUtf8()); - auto limitedNodeList = DependencyManager::get(); - limitedNodeList->eachMatchingNode([](const SharedNodePointer& node) { - return node->getType() == NodeType::EntityServer && node->getActiveSocket(); - }, [&_url, limitedNodeList](const SharedNodePointer& octreeNode) { - auto octreeFilePacket = NLPacket::create(PacketType::OctreeFileReplacementFromUrl, _url.size(), true); - octreeFilePacket->write(_url); - limitedNodeList->sendPacket(std::move(octreeFilePacket), *octreeNode); - return true; - }); - DependencyManager::get()->handleLookupString(DOMAIN_SPAWNING_POINT); - methodDetails = "SuccessfulRequestToReplaceContent"; + if (agreeToReplaceContent) { + // Given confirmation, send request to domain server to replace content + qCDebug(interfaceapp) << "Attempting to replace domain content: " << url; + QByteArray _url(url.toUtf8()); + auto limitedNodeList = DependencyManager::get(); + limitedNodeList->eachMatchingNode([](const SharedNodePointer& node) { + return node->getType() == NodeType::EntityServer && node->getActiveSocket(); + }, [&_url, limitedNodeList](const SharedNodePointer& octreeNode) { + auto octreeFilePacket = NLPacket::create(PacketType::OctreeFileReplacementFromUrl, _url.size(), true); + octreeFilePacket->write(_url); + limitedNodeList->sendPacket(std::move(octreeFilePacket), *octreeNode); + return true; + }); + DependencyManager::get()->handleLookupString(DOMAIN_SPAWNING_POINT); + methodDetails = "SuccessfulRequestToReplaceContent"; + } else { + methodDetails = "UserDeclinedToReplaceContent"; + } } else { - methodDetails = "UserDeclinedToReplaceContent"; + methodDetails = "ContentSetDidNotOriginateFromMarketplace"; } } else { - methodDetails = "UserDoesNotHavePermissionToReplaceContent"; - OffscreenUi::warning("Unable to replace content", "You do not have permissions to replace domain content", - QMessageBox::Ok, QMessageBox::Ok); + methodDetails = "UserDoesNotHavePermissionToReplaceContent"; + OffscreenUi::warning("Unable to replace content", "You do not have permissions to replace domain content", + QMessageBox::Ok, QMessageBox::Ok); } QJsonObject messageProperties = { { "status", methodDetails }, @@ -6166,7 +6172,6 @@ bool Application::askToReplaceDomainContent(const QString& url) { }; UserActivityLogger::getInstance().logAction("replace_domain_content", messageProperties); return false; - } void Application::displayAvatarAttachmentWarning(const QString& message) const { From 4e81ebf85cafce1d7deebac1311dc110bbe4d404 Mon Sep 17 00:00:00 2001 From: Cain Kilgore Date: Thu, 10 Aug 2017 22:53:35 +0100 Subject: [PATCH 23/54] Added Assets for Web Browser MP Script --- .../qml/controls-uit/WebGlyphButton.qml | 48 ++++ interface/resources/qml/hifi/WebBrowser.qml | 253 ++++++++++++++++++ 2 files changed, 301 insertions(+) create mode 100644 interface/resources/qml/controls-uit/WebGlyphButton.qml create mode 100644 interface/resources/qml/hifi/WebBrowser.qml diff --git a/interface/resources/qml/controls-uit/WebGlyphButton.qml b/interface/resources/qml/controls-uit/WebGlyphButton.qml new file mode 100644 index 0000000000..15524e4188 --- /dev/null +++ b/interface/resources/qml/controls-uit/WebGlyphButton.qml @@ -0,0 +1,48 @@ +// +// GlyphButton.qml +// +// Created by Vlad Stelmahovsky on 2017-06-21 +// Copyright 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 +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 as Original +import QtQuick.Controls.Styles 1.4 + +import "../styles-uit" + +Original.Button { + id: control + + property int colorScheme: hifi.colorSchemes.light + property string glyph: "" + property int size: 32 + //colors + readonly property color normalColor: "#AFAFAF" + readonly property color hoverColor: "#00B4EF" + readonly property color clickedColor: "#FFFFFF" + readonly property color disabledColor: "#575757" + + style: ButtonStyle { + background: Item {} + + + label: HiFiGlyphs { + color: control.enabled ? (control.pressed ? control.clickedColor : + (control.hovered ? control.hoverColor : control.normalColor)) : + control.disabledColor + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + anchors { + // Tweak horizontal alignment so that it looks right. + left: parent.left + leftMargin: -0.5 + } + text: control.glyph + size: control.size + } + } +} diff --git a/interface/resources/qml/hifi/WebBrowser.qml b/interface/resources/qml/hifi/WebBrowser.qml new file mode 100644 index 0000000000..f639586668 --- /dev/null +++ b/interface/resources/qml/hifi/WebBrowser.qml @@ -0,0 +1,253 @@ +// +// WebBrowser.qml +// +// +// Created by Vlad Stelmahovsky on 06/22/2017 +// Copyright 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 +// + +import QtQuick 2.5 +import QtQuick.Controls 1.5 as QQControls +import QtQuick.Layouts 1.3 +import QtQuick.Controls.Styles 1.4 + +import QtWebEngine 1.2 +import QtWebChannel 1.0 + +import "../styles-uit" +import "../controls-uit" as HifiControls +import "../windows" +import "../controls" + +Rectangle { + id: root; + + HifiConstants { id: hifi; } + + property string title: ""; + signal sendToScript(var message); + property bool keyboardEnabled: true // FIXME - Keyboard HMD only: Default to false + property bool keyboardRaised: false + property bool punctuationMode: false + + + color: hifi.colors.baseGray; + + // only show the title if loaded through a "loader" + + Column { + spacing: 2 + width: parent.width; + + RowLayout { + width: parent.width; + height: 48 + + HifiControls.WebGlyphButton { + enabled: webEngineView.canGoBack + glyph: hifi.glyphs.backward; + anchors.verticalCenter: parent.verticalCenter; + size: 38; + onClicked: { + webEngineView.goBack() + } + } + + HifiControls.WebGlyphButton { + enabled: webEngineView.canGoForward + glyph: hifi.glyphs.forward; + anchors.verticalCenter: parent.verticalCenter; + size: 38; + onClicked: { + webEngineView.goForward() + } + } + + QQControls.TextField { + id: addressBar + + Image { + anchors.verticalCenter: addressBar.verticalCenter; + x: 5 + z: 2 + id: faviconImage + width: 16; height: 16 + sourceSize: Qt.size(width, height) + source: webEngineView.icon + } + + HifiControls.WebGlyphButton { + glyph: webEngineView.loading ? hifi.glyphs.closeSmall : hifi.glyphs.reloadSmall; + anchors.verticalCenter: parent.verticalCenter; + width: hifi.dimensions.controlLineHeight + z: 2 + x: addressBar.width - 28 + onClicked: { + if (webEngineView.loading) { + webEngineView.stop() + } else { + reloadTimer.start() + } + } + } + + style: TextFieldStyle { + padding { + left: 26; + right: 26 + } + } + focus: true + Layout.fillWidth: true + text: webEngineView.url + onAccepted: webEngineView.url = text + } + HifiControls.WebGlyphButton { + checkable: true + //only QtWebEngine 1.3 + //checked: webEngineView.audioMuted + glyph: checked ? hifi.glyphs.unmuted : hifi.glyphs.muted + anchors.verticalCenter: parent.verticalCenter; + width: hifi.dimensions.controlLineHeight + onClicked: { + webEngineView.triggerWebAction(WebEngineView.ToggleMediaMute) + } + } + } + + QQControls.ProgressBar { + id: loadProgressBar + style: ProgressBarStyle { + background: Rectangle { + color: "#6A6A6A" + } + progress: Rectangle{ + color: "#00B4EF" + } + } + + width: parent.width; + minimumValue: 0 + maximumValue: 100 + value: webEngineView.loadProgress + height: 2 + } + + HifiControls.BaseWebView { + id: webEngineView + focus: true + objectName: "tabletWebEngineView" + + url: "http://www.highfidelity.com" + property real webViewHeight: root.height - loadProgressBar.height - 48 - 4 + + width: parent.width; + height: keyboardEnabled && keyboardRaised ? webViewHeight - keyboard.height : webViewHeight + + profile: HFTabletWebEngineProfile; + + property string userScriptUrl: "" + + // creates a global EventBridge object. + WebEngineScript { + id: createGlobalEventBridge + sourceCode: eventBridgeJavaScriptToInject + injectionPoint: WebEngineScript.DocumentCreation + worldId: WebEngineScript.MainWorld + } + + // detects when to raise and lower virtual keyboard + WebEngineScript { + id: raiseAndLowerKeyboard + injectionPoint: WebEngineScript.Deferred + sourceUrl: resourceDirectoryUrl + "/html/raiseAndLowerKeyboard.js" + worldId: WebEngineScript.MainWorld + } + + // User script. + WebEngineScript { + id: userScript + sourceUrl: webEngineView.userScriptUrl + injectionPoint: WebEngineScript.DocumentReady // DOM ready but page load may not be finished. + worldId: WebEngineScript.MainWorld + } + + userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ] + + settings.autoLoadImages: true + settings.javascriptEnabled: true + settings.errorPageEnabled: true + settings.pluginsEnabled: true + settings.fullScreenSupportEnabled: false + //from WebEngine 1.3 + // settings.autoLoadIconsForPage: false + // settings.touchIconsEnabled: false + + onCertificateError: { + error.defer(); + } + + Component.onCompleted: { + webChannel.registerObject("eventBridge", eventBridge); + webChannel.registerObject("eventBridgeWrapper", eventBridgeWrapper); + webEngineView.profile.httpUserAgent = "Mozilla/5.0 Chrome (HighFidelityInterface)"; + } + + onFeaturePermissionRequested: { + grantFeaturePermission(securityOrigin, feature, true); + } + + onNewViewRequested: { + if (!request.userInitiated) { + print("Warning: Blocked a popup window."); + } + } + + onRenderProcessTerminated: { + var status = ""; + switch (terminationStatus) { + case WebEngineView.NormalTerminationStatus: + status = "(normal exit)"; + break; + case WebEngineView.AbnormalTerminationStatus: + status = "(abnormal exit)"; + break; + case WebEngineView.CrashedTerminationStatus: + status = "(crashed)"; + break; + case WebEngineView.KilledTerminationStatus: + status = "(killed)"; + break; + } + + print("Render process exited with code " + exitCode + " " + status); + reloadTimer.running = true; + } + + onWindowCloseRequested: { + } + + Timer { + id: reloadTimer + interval: 0 + running: false + repeat: false + onTriggered: webEngineView.reload() + } + } + } + + HifiControls.Keyboard { + id: keyboard + raised: parent.keyboardEnabled && parent.keyboardRaised + numeric: parent.punctuationMode + anchors { + left: parent.left + right: parent.right + bottom: parent.bottom + } + } +} From ae98974d792345e91cbf7c3515499aae4ab7be4a Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 10 Aug 2017 15:52:51 -0700 Subject: [PATCH 24/54] improve 14-dop generation for avatar joint collision Also added debug rendering functionality. --- interface/src/avatar/MyAvatar.cpp | 31 ++++++ libraries/fbx/src/FBXReader.cpp | 8 +- libraries/fbx/src/FBXReader.h | 5 +- libraries/shared/src/GeometryUtil.cpp | 147 ++++++++++++++++++++++++++ libraries/shared/src/GeometryUtil.h | 7 ++ 5 files changed, 195 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 36295e87b8..cc2ad686a4 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1805,6 +1805,37 @@ void MyAvatar::postUpdate(float deltaTime) { AnimPose postUpdateRoomPose(_sensorToWorldMatrix); updateHoldActions(_prePhysicsRoomPose, postUpdateRoomPose); + + bool _enableDebugDrawDetailedCollision = true; + if (_enableDebugDrawDetailedCollision) { + AnimPose rigToWorldPose(glm::vec3(1.0f), Quaternions::Y_180 * getRotation(), getPosition()); + const int NUM_DEBUG_COLORS = 7; + const glm::vec4 DEBUG_COLORS[NUM_DEBUG_COLORS] = { + glm::vec4(1.0f, 1.0f, 1.0f, 1.0f), + glm::vec4(1.0f, 0.0f, 0.0f, 1.0f), + glm::vec4(0.0f, 1.0f, 0.0f, 1.0f), + glm::vec4(0.25f, 0.25f, 1.0f, 1.0f), + glm::vec4(1.0f, 1.0f, 0.0f, 1.0f), + glm::vec4(0.25f, 1.0f, 1.0f, 1.0f), + glm::vec4(1.0f, 0.25f, 1.0f, 1.0f), + }; + + if (_skeletonModel && _skeletonModel->isLoaded()) { + const Rig& rig = _skeletonModel->getRig(); + const FBXGeometry& geometry = _skeletonModel->getFBXGeometry(); + for (int i = 0; i < rig.getJointStateCount(); i++) { + AnimPose jointPose; + rig.getAbsoluteJointPoseInRigFrame(i, jointPose); + const FBXJointShapeInfo& shapeInfo = geometry.joints[i].shapeInfo; + const AnimPose pose = rigToWorldPose * jointPose; + for (int j = 0; j < shapeInfo.debugLines.size() / 2; j++) { + glm::vec3 pointA = pose.xformPoint(shapeInfo.debugLines[2 * j]); + glm::vec3 pointB = pose.xformPoint(shapeInfo.debugLines[2 * j + 1]); + DebugDraw::getInstance().drawRay(pointA, pointB, DEBUG_COLORS[i % NUM_DEBUG_COLORS]); + } + } + } + } } void MyAvatar::preDisplaySide(RenderArgs* renderArgs) { diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 6d4f586c52..cd313dbd05 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1682,8 +1682,8 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS int newIndex = it.value(); // remember vertices with at least 1/4 weight - const float EXPANSION_WEIGHT_THRESHOLD = 0.99f; - if (weight > EXPANSION_WEIGHT_THRESHOLD) { + const float EXPANSION_WEIGHT_THRESHOLD = 0.25f; + 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); @@ -1788,6 +1788,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS avgPoint += points[j]; } avgPoint /= (float)points.size(); + joint.shapeInfo.avgPoint = avgPoint; // compute a k-Dop bounding volume for (uint32_t j = 0; j < cardinalDirections.size(); ++j) { @@ -1803,8 +1804,11 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS } } joint.shapeInfo.points.push_back(avgPoint + maxDot * cardinalDirections[j]); + joint.shapeInfo.dots.push_back(maxDot); joint.shapeInfo.points.push_back(avgPoint + minDot * cardinalDirections[j]); + joint.shapeInfo.dots.push_back(-minDot); } + generateBoundryLinesForDop14(joint.shapeInfo.dots, joint.shapeInfo.avgPoint, joint.shapeInfo.debugLines); } } geometry.palmDirection = parseVec3(mapping.value("palmDirection", "0, -1, 0").toString()); diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index f73088e7a1..170bbbf366 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -56,7 +56,10 @@ public: struct FBXJointShapeInfo { // same units and frame as FBXJoint.translation - QVector points; + glm::vec3 avgPoint; + std::vector dots; + std::vector points; + std::vector debugLines; }; /// A single joint (transformation node) extracted from an FBX document. diff --git a/libraries/shared/src/GeometryUtil.cpp b/libraries/shared/src/GeometryUtil.cpp index 4ae907eb3b..0b889e4c24 100644 --- a/libraries/shared/src/GeometryUtil.cpp +++ b/libraries/shared/src/GeometryUtil.cpp @@ -17,6 +17,7 @@ #include #include "NumericalConstants.h" +#include "glmHelpers.h" glm::vec3 computeVectorFromPointToSegment(const glm::vec3& point, const glm::vec3& start, const glm::vec3& end) { // compute the projection of the point vector onto the segment vector @@ -657,3 +658,149 @@ bool findPlaneFromPoints(const glm::vec3* points, size_t numPoints, glm::vec3& p planeNormalOut = glm::normalize(dir); return true; } + +bool findIntersectionOfThreePlanes(const glm::vec4& planeA, const glm::vec4& planeB, const glm::vec4& planeC, glm::vec3& intersectionPointOut) { + glm::vec3 normalA(planeA); + glm::vec3 normalB(planeB); + glm::vec3 normalC(planeC); + glm::vec3 u = glm::cross(normalB, normalC); + float denom = glm::dot(normalA, u); + if (fabsf(denom) < EPSILON) { + return false; // planes do not intersect in a point. + } else { + intersectionPointOut = (planeA.w * u + glm::cross(normalA, planeC.w * normalB - planeB.w * normalC)) / denom; + return true; + } +} + +const float INV_SQRT_3 = 1.0f / sqrtf(3.0f); +const int DOP14_COUNT = 14; +const glm::vec3 DOP14_NORMALS[DOP14_COUNT] = { + Vectors::UNIT_X, + -Vectors::UNIT_X, + Vectors::UNIT_Y, + -Vectors::UNIT_Y, + Vectors::UNIT_Z, + -Vectors::UNIT_Z, + glm::vec3(INV_SQRT_3, INV_SQRT_3, INV_SQRT_3), + -glm::vec3(INV_SQRT_3, INV_SQRT_3, INV_SQRT_3), + glm::vec3(INV_SQRT_3, -INV_SQRT_3, INV_SQRT_3), + -glm::vec3(INV_SQRT_3, -INV_SQRT_3, INV_SQRT_3), + glm::vec3(INV_SQRT_3, INV_SQRT_3, -INV_SQRT_3), + -glm::vec3(INV_SQRT_3, INV_SQRT_3, -INV_SQRT_3), + glm::vec3(INV_SQRT_3, -INV_SQRT_3, -INV_SQRT_3), + -glm::vec3(INV_SQRT_3, -INV_SQRT_3, -INV_SQRT_3) +}; + +const std::tuple DOP14_PLANE_COMBINATIONS[] = { + {0,2,4}, {0,2,5}, {0,2,6}, {0,2,7}, {0,2,8}, {0,2,9}, {0,2,10}, {0,2,11}, {0,2,12}, {0,2,13}, + {0,3,4}, {0,3,5}, {0,3,6}, {0,3,7}, {0,3,8}, {0,3,9}, {0,3,10}, {0,3,11}, {0,3,12}, {0,3,13}, + {0,4,6}, {0,4,7}, {0,4,8}, {0,4,9}, {0,4,10}, {0,4,11}, {0,4,12}, {0,4,13}, + {0,5,6}, {0,5,7}, {0,5,8}, {0,5,9}, {0,5,10}, {0,5,11}, {0,5,12}, {0,5,13}, + {0,6,8}, {0,6,9}, {0,6,10}, {0,6,11}, {0,6,12}, {0,6,13}, + {0,7,8}, {0,7,9}, {0,7,10}, {0,7,11}, {0,7,12}, {0,7,13}, + {0,8,10}, {0,8,11}, {0,8,12}, {0,8,13}, {0,9,10}, + {0,9,11}, {0,9,12}, {0,9,13}, + {0,10,12}, {0,10,13}, + {0,11,12}, {0,11,13}, + {1,2,4}, {1,2,5}, {1,2,6}, {1,2,7}, {1,2,8}, {1,2,9}, {1,2,10}, {1,2,11}, {1,2,12}, {1,2,13}, + {1,3,4}, {1,3,5}, {1,3,6}, {1,3,7}, {1,3,8}, {1,3,9}, {1,3,10}, {1,3,11}, {1,3,12}, {1,3,13}, + {1,4,6}, {1,4,7}, {1,4,8}, {1,4,9}, {1,4,10}, {1,4,11}, {1,4,12}, {1,4,13}, + {1,5,6}, {1,5,7}, {1,5,8}, {1,5,9}, {1,5,10}, {1,5,11}, {1,5,12}, {1,5,13}, + {1,6,8}, {1,6,9}, {1,6,10}, {1,6,11}, {1,6,12}, {1,6,13}, + {1,7,8}, {1,7,9}, {1,7,10}, {1,7,11}, {1,7,12}, {1,7,13}, + {1,8,10}, {1,8,11}, {1,8,12}, {1,8,13}, + {1,9,10}, {1,9,11}, {1,9,12}, {1,9,13}, + {1,10,12}, {1,10,13}, + {1,11,12}, {1,11,13}, + {2,4,6}, {2,4,7}, {2,4,8}, {2,4,9}, {2,4,10}, {2,4,11}, {2,4,12}, {2,4,13}, + {2,5,6}, {2,5,7}, {2,5,8}, {2,5,9}, {2,5,10}, {2,5,11}, {2,5,12}, {2,5,13}, + {2,6,8}, {2,6,9}, {2,6,10}, {2,6,11}, {2,6,12}, {2,6,13}, + {2,7,8}, {2,7,9}, {2,7,10}, {2,7,11}, {2,7,12}, {2,7,13}, + {2,8,10}, {2,8,11}, {2,8,12}, {2,8,13}, + {2,9,10}, {2,9,11}, {2,9,12}, {2,9,13}, + {2,10,12}, {2,10,13}, + {2,11,12}, {2,11,13}, + {3,4,6}, {3,4,7}, {3,4,8}, {3,4,9}, {3,4,10}, {3,4,11}, {3,4,12}, {3,4,13}, + {3,5,6}, {3,5,7}, {3,5,8}, {3,5,9}, {3,5,10}, {3,5,11}, {3,5,12}, {3,5,13}, + {3,6,8}, {3,6,9}, {3,6,10}, {3,6,11}, {3,6,12}, {3,6,13}, + {3,7,8}, {3,7,9}, {3,7,10}, {3,7,11}, {3,7,12}, {3,7,13}, + {3,8,10}, {3,8,11}, {3,8,12}, {3,8,13}, + {3,9,10}, {3,9,11}, {3,9,12}, {3,9,13}, + {3,10,12}, {3,10,13}, + {3,11,12}, {3,11,13}, + {4,6,8}, {4,6,9}, {4,6,10}, {4,6,11}, {4,6,12}, {4,6,13}, + {4,7,8}, {4,7,9}, {4,7,10}, {4,7,11}, {4,7,12}, {4,7,13}, + {4,8,10}, {4,8,11}, {4,8,12}, {4,8,13}, + {4,9,10}, {4,9,11}, {4,9,12}, {4,9,13}, + {4,10,12}, {4,10,13}, + {4,11,12}, {4,11,13}, + {5,6,8}, {5,6,9}, {5,6,10}, {5,6,11}, {5,6,12}, {5,6,13}, + {5,7,8}, {5,7,9}, {5,7,10}, {5,7,11}, {5,7,12}, {5,7,13}, + {5,8,10}, {5,8,11}, {5,8,12}, {5,8,13}, + {5,9,10}, {5,9,11}, {5,9,12}, {5,9,13}, + {5,10,12}, {5,10,13}, + {5,11,12}, {5,11,13}, + {6,8,10}, {6,8,11}, {6,8,12}, {6,8,13}, + {6,9,10}, {6,9,11}, {6,9,12}, {6,9,13}, + {6,10,12}, {6,10,13}, + {6,11,12}, {6,11,13}, + {7,8,10}, {7,8,11}, {7,8,12}, {7,8,13}, + {7,9,10}, {7,9,11}, {7,9,12}, {7,9,13}, + {7,10,12}, {7,10,13}, + {7,11,12}, {7,11,13}, + {8,10,12}, {8,10,13}, + {8,11,12}, {8,11,13}, + {9,10,12}, {9,10,13}, + {9,11,12}, {9,11,13} +}; + +void generateBoundryLinesForDop14(const std::vector& dots, const glm::vec3& center, std::vector& linesOut) { + if (dots.size() != DOP14_COUNT) { + return; + } + + // iterate over all purmutations of non-parallel planes. + // find all the vertices that lie on the surface of the k-dop + std::vector vertices; + for (auto& tuple : DOP14_PLANE_COMBINATIONS) { + int i = std::get<0>(tuple); + int j = std::get<1>(tuple); + int k = std::get<2>(tuple); + glm::vec4 planeA(DOP14_NORMALS[i], dots[i]); + glm::vec4 planeB(DOP14_NORMALS[j], dots[j]); + glm::vec4 planeC(DOP14_NORMALS[k], dots[k]); + glm::vec3 intersectionPoint; + const float IN_FRONT_MARGIN = 0.01f; + if (findIntersectionOfThreePlanes(planeA, planeB, planeC, intersectionPoint)) { + bool inFront = false; + for (int p = 0; p < DOP14_COUNT; p++) { + if (glm::dot(DOP14_NORMALS[p], intersectionPoint) > dots[p] + IN_FRONT_MARGIN) { + inFront = true; + } + } + if (!inFront) { + vertices.push_back(intersectionPoint); + } + } + } + + // build a set of lines between these vertices, that also lie on the surface of the k-dop. + for (int i = 0; i < vertices.size(); i++) { + for (int j = i; j < vertices.size(); j++) { + glm::vec3 midPoint = (vertices[i] + vertices[j]) * 0.5f; + int onSurfaceCount = 0; + const float SURFACE_MARGIN = 0.01f; + for (int p = 0; p < DOP14_COUNT; p++) { + float d = glm::dot(DOP14_NORMALS[p], midPoint); + if (d > dots[p] - SURFACE_MARGIN && d < dots[p] + SURFACE_MARGIN) { + onSurfaceCount++; + } + } + if (onSurfaceCount > 1) { + linesOut.push_back(vertices[i] + center); + linesOut.push_back(vertices[j] + center); + } + } + } +} diff --git a/libraries/shared/src/GeometryUtil.h b/libraries/shared/src/GeometryUtil.h index a5ee67748b..eb9424d938 100644 --- a/libraries/shared/src/GeometryUtil.h +++ b/libraries/shared/src/GeometryUtil.h @@ -13,6 +13,7 @@ #define hifi_GeometryUtil_h #include +#include glm::vec3 computeVectorFromPointToSegment(const glm::vec3& point, const glm::vec3& start, const glm::vec3& end); @@ -166,4 +167,10 @@ private: // given a set of points, compute a best fit plane that passes as close as possible through all the points. bool findPlaneFromPoints(const glm::vec3* points, size_t numPoints, glm::vec3& planeNormalOut, glm::vec3& pointOnPlaneOut); +// plane equation is specified by ax + by + cz + d = 0. +// the coefficents are passed in as a vec4. (a, b, c, d) +bool findIntersectionOfThreePlanes(const glm::vec4& planeA, const glm::vec4& planeB, const glm::vec4& planeC, glm::vec3& intersectionPointOut); + +void generateBoundryLinesForDop14(const std::vector& dots, const glm::vec3& center, std::vector& linesOut); + #endif // hifi_GeometryUtil_h From 49adf04913147f15823939931f6b24c82d4a6222 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 10 Aug 2017 16:36:09 -0700 Subject: [PATCH 25/54] Added Developer > Avatar > Show Detailed Collision menu option --- interface/src/Menu.cpp | 2 ++ interface/src/Menu.h | 1 + interface/src/avatar/MyAvatar.cpp | 5 ++++- interface/src/avatar/MyAvatar.h | 2 ++ 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 56bd3eb749..2c4a515736 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -555,6 +555,8 @@ Menu::Menu() { avatar.get(), SLOT(setEnableDebugDrawIKConstraints(bool))); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderIKChains, 0, false, avatar.get(), SLOT(setEnableDebugDrawIKChains(bool))); + addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderDetailedCollision, 0, false, + avatar.get(), SLOT(setEnableDebugDrawDetailedCollision(bool))); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ActionMotorControl, Qt::CTRL | Qt::SHIFT | Qt::Key_K, true, avatar.get(), SLOT(updateMotionBehaviorFromMenu()), diff --git a/interface/src/Menu.h b/interface/src/Menu.h index a81ef9ac86..4e21cfa4ac 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -162,6 +162,7 @@ namespace MenuOption { const QString RenderIKTargets = "Show IK Targets"; const QString RenderIKConstraints = "Show IK Constraints"; const QString RenderIKChains = "Show IK Chains"; + const QString RenderDetailedCollision = "Show Detailed Collision"; const QString ResetAvatarSize = "Reset Avatar Size"; const QString ResetSensors = "Reset Sensors"; const QString RunningScripts = "Running Scripts..."; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index cc2ad686a4..3048d04247 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1060,6 +1060,10 @@ void MyAvatar::setEnableDebugDrawIKConstraints(bool isEnabled) { _enableDebugDrawIKConstraints = isEnabled; } +void MyAvatar::setEnableDebugDrawDetailedCollision(bool isEnabled) { + _enableDebugDrawDetailedCollision = isEnabled; +} + void MyAvatar::setEnableDebugDrawIKChains(bool isEnabled) { _enableDebugDrawIKChains = isEnabled; } @@ -1806,7 +1810,6 @@ void MyAvatar::postUpdate(float deltaTime) { updateHoldActions(_prePhysicsRoomPose, postUpdateRoomPose); - bool _enableDebugDrawDetailedCollision = true; if (_enableDebugDrawDetailedCollision) { AnimPose rigToWorldPose(glm::vec3(1.0f), Quaternions::Y_180 * getRotation(), getPosition()); const int NUM_DEBUG_COLORS = 7; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index dc4357be52..c7fe309894 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -553,6 +553,7 @@ public slots: void setEnableDebugDrawIKTargets(bool isEnabled); void setEnableDebugDrawIKConstraints(bool isEnabled); void setEnableDebugDrawIKChains(bool isEnabled); + void setEnableDebugDrawDetailedCollision(bool isEnabled); bool getEnableMeshVisible() const { return _skeletonModel->isVisible(); } void setEnableMeshVisible(bool isEnabled); @@ -757,6 +758,7 @@ private: bool _enableDebugDrawIKTargets { false }; bool _enableDebugDrawIKConstraints { false }; bool _enableDebugDrawIKChains { false }; + bool _enableDebugDrawDetailedCollision { false }; AudioListenerMode _audioListenerMode; glm::vec3 _customListenPosition; From 9e1218b4a4aeecad0635e2962be2f384b2404660 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 11 Aug 2017 14:18:40 -0700 Subject: [PATCH 26/54] Use k-dop collision to prevent hands from entering body. --- interface/src/avatar/MySkeletonModel.cpp | 22 +++- libraries/animation/src/Rig.cpp | 147 +++++++++++++++++++---- libraries/animation/src/Rig.h | 12 +- 3 files changed, 150 insertions(+), 31 deletions(-) diff --git a/interface/src/avatar/MySkeletonModel.cpp b/interface/src/avatar/MySkeletonModel.cpp index 6d468c3f30..89e4368515 100644 --- a/interface/src/avatar/MySkeletonModel.cpp +++ b/interface/src/avatar/MySkeletonModel.cpp @@ -124,12 +124,26 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { } } - params.bodyCapsuleRadius = myAvatar->getCharacterController()->getCapsuleRadius(); - params.bodyCapsuleHalfHeight = myAvatar->getCharacterController()->getCapsuleHalfHeight(); - params.bodyCapsuleLocalOffset = myAvatar->getCharacterController()->getCapsuleLocalOffset(); - params.isTalking = head->getTimeWithoutTalking() <= 1.5f; + // pass detailed torso k-dops to rig. + int hipsJoint = _rig.indexOfJoint("Hips"); + if (hipsJoint >= 0) { + params.hipsShapeInfo = geometry.joints[hipsJoint].shapeInfo; + } + int spineJoint = _rig.indexOfJoint("Spine"); + if (spineJoint >= 0) { + params.spineShapeInfo = geometry.joints[spineJoint].shapeInfo; + } + int spine1Joint = _rig.indexOfJoint("Spine1"); + if (spine1Joint >= 0) { + params.spine1ShapeInfo = geometry.joints[spine1Joint].shapeInfo; + } + int spine2Joint = _rig.indexOfJoint("Spine2"); + if (spine2Joint >= 0) { + params.spine2ShapeInfo = geometry.joints[spine2Joint].shapeInfo; + } + _rig.updateFromControllerParameters(params, deltaTime); Rig::CharacterControllerState ccState = convertCharacterControllerState(myAvatar->getCharacterController()->getState()); diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 21f98d3e01..15886a1212 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1099,35 +1099,139 @@ void Rig::updateHead(bool headEnabled, bool hipsEnabled, const AnimPose& headPos } } -void Rig::updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnabled, bool leftArmEnabled, bool rightArmEnabled, float dt, - const AnimPose& leftHandPose, const AnimPose& rightHandPose, - float bodyCapsuleRadius, float bodyCapsuleHalfHeight, const glm::vec3& bodyCapsuleLocalOffset) { +const float INV_SQRT_3 = 1.0f / sqrtf(3.0f); +const int DOP14_COUNT = 14; +const glm::vec3 DOP14_NORMALS[DOP14_COUNT] = { + Vectors::UNIT_X, + -Vectors::UNIT_X, + Vectors::UNIT_Y, + -Vectors::UNIT_Y, + Vectors::UNIT_Z, + -Vectors::UNIT_Z, + glm::vec3(INV_SQRT_3, INV_SQRT_3, INV_SQRT_3), + -glm::vec3(INV_SQRT_3, INV_SQRT_3, INV_SQRT_3), + glm::vec3(INV_SQRT_3, -INV_SQRT_3, INV_SQRT_3), + -glm::vec3(INV_SQRT_3, -INV_SQRT_3, INV_SQRT_3), + glm::vec3(INV_SQRT_3, INV_SQRT_3, -INV_SQRT_3), + -glm::vec3(INV_SQRT_3, INV_SQRT_3, -INV_SQRT_3), + glm::vec3(INV_SQRT_3, -INV_SQRT_3, -INV_SQRT_3), + -glm::vec3(INV_SQRT_3, -INV_SQRT_3, -INV_SQRT_3) +}; - // Use this capsule to represent the avatar body. - int hipsIndex = indexOfJoint("Hips"); - glm::vec3 hipsTrans; - if (hipsIndex >= 0) { - hipsTrans = _internalPoseSet._absolutePoses[hipsIndex].trans(); +// returns true if the given point lies in side of the k-dop, specified by shapeInfo & shapePose. +// if the given point does lie within the k-dop, it also returns the amount of displacement necessary to push that point outward +// such that it lies on the surface of the kdop. +static bool findPointKDopDisplacement(const glm::vec3& point, const AnimPose& shapePose, const FBXJointShapeInfo& shapeInfo, glm::vec3& displacementOut) { + + // transform point into local space of jointShape. + glm::vec3 localPoint = shapePose.inverse().xformPoint(point); + + // Only works for 14-dop shape infos. + assert(shapeInfo.dots.size() == DOP14_COUNT); + if (shapeInfo.dots.size() != DOP14_COUNT) { + return false; } - const glm::vec3 bodyCapsuleCenter = hipsTrans - bodyCapsuleLocalOffset; - const glm::vec3 bodyCapsuleStart = bodyCapsuleCenter - glm::vec3(0, bodyCapsuleHalfHeight, 0); - const glm::vec3 bodyCapsuleEnd = bodyCapsuleCenter + glm::vec3(0, bodyCapsuleHalfHeight, 0); + glm::vec3 minDisplacement(FLT_MAX); + float minDisplacementLen = FLT_MAX; + glm::vec3 p = localPoint - shapeInfo.avgPoint; + float pLen = glm::length(p); + if (pLen > 0.0f) { + int slabCount = 0; + for (int i = 0; i < DOP14_COUNT; i++) { + float dot = glm::dot(p, DOP14_NORMALS[i]); + if (dot > 0.0f && dot < shapeInfo.dots[i]) { + slabCount++; + float distToPlane = pLen * (shapeInfo.dots[i] / dot); + float displacementLen = distToPlane - pLen; + + // keep track of the smallest displacement + if (displacementLen < minDisplacementLen) { + minDisplacementLen = displacementLen; + minDisplacement = (p / pLen) * displacementLen; + } + } + } + if (slabCount == (DOP14_COUNT / 2) && minDisplacementLen != FLT_MAX) { + // we are within the k-dop so push the point along the minimum displacement found + displacementOut = shapePose.xformVectorFast(minDisplacement); + return true; + } else { + // point is outside of kdop + return false; + } + } else { + // point is directly on top of shapeInfo.avgPoint. + // push the point out along the x axis. + displacementOut = shapePose.xformVectorFast(shapeInfo.points[0]); + return true; + } +} + +glm::vec3 Rig::deflectHandFromTorso(const glm::vec3& handPosition, const FBXJointShapeInfo& hipsShapeInfo, const FBXJointShapeInfo& spineShapeInfo, + const FBXJointShapeInfo& spine1ShapeInfo, const FBXJointShapeInfo& spine2ShapeInfo) const { + glm::vec3 position = handPosition; + glm::vec3 displacement; + int hipsJoint = indexOfJoint("Hips"); + if (hipsJoint >= 0) { + AnimPose hipsPose; + if (getAbsoluteJointPoseInRigFrame(hipsJoint, hipsPose)) { + if (findPointKDopDisplacement(position, hipsPose, hipsShapeInfo, displacement)) { + position += displacement; + } + } + } + + int spineJoint = indexOfJoint("Spine"); + if (spineJoint >= 0) { + AnimPose spinePose; + if (getAbsoluteJointPoseInRigFrame(spineJoint, spinePose)) { + if (findPointKDopDisplacement(position, spinePose, spineShapeInfo, displacement)) { + position += displacement; + } + } + } + + int spine1Joint = indexOfJoint("Spine1"); + if (spine1Joint >= 0) { + AnimPose spine1Pose; + if (getAbsoluteJointPoseInRigFrame(spine1Joint, spine1Pose)) { + if (findPointKDopDisplacement(position, spine1Pose, spine1ShapeInfo, displacement)) { + position += displacement; + } + } + } + + int spine2Joint = indexOfJoint("Spine2"); + if (spine2Joint >= 0) { + AnimPose spine2Pose; + if (getAbsoluteJointPoseInRigFrame(spine2Joint, spine2Pose)) { + if (findPointKDopDisplacement(position, spine2Pose, spine2ShapeInfo, displacement)) { + position += displacement; + } + } + } + + return position; +} + +void Rig::updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnabled, bool leftArmEnabled, bool rightArmEnabled, float dt, + const AnimPose& leftHandPose, const AnimPose& rightHandPose, + const FBXJointShapeInfo& hipsShapeInfo, const FBXJointShapeInfo& spineShapeInfo, + const FBXJointShapeInfo& spine1ShapeInfo, const FBXJointShapeInfo& spine2ShapeInfo) { - const float HAND_RADIUS = 0.05f; const float ELBOW_POLE_VECTOR_BLEND_FACTOR = 0.95f; + int hipsIndex = indexOfJoint("Hips"); + if (leftHandEnabled) { glm::vec3 handPosition = leftHandPose.trans(); glm::quat handRotation = leftHandPose.rot(); if (!hipsEnabled) { - // prevent the hand IK targets from intersecting the body capsule - glm::vec3 displacement; - if (findSphereCapsulePenetration(handPosition, HAND_RADIUS, bodyCapsuleStart, bodyCapsuleEnd, bodyCapsuleRadius, displacement)) { - handPosition -= displacement; - } + // prevent the hand IK targets from intersecting the torso + handPosition = deflectHandFromTorso(handPosition, hipsShapeInfo, spineShapeInfo, spine1ShapeInfo, spine2ShapeInfo); } _animVars.set("leftHandPosition", handPosition); @@ -1173,11 +1277,8 @@ void Rig::updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnab glm::quat handRotation = rightHandPose.rot(); if (!hipsEnabled) { - // prevent the hand IK targets from intersecting the body capsule - glm::vec3 displacement; - if (findSphereCapsulePenetration(handPosition, HAND_RADIUS, bodyCapsuleStart, bodyCapsuleEnd, bodyCapsuleRadius, displacement)) { - handPosition -= displacement; - } + // prevent the hand IK targets from intersecting the torso + handPosition = deflectHandFromTorso(handPosition, hipsShapeInfo, spineShapeInfo, spine1ShapeInfo, spine2ShapeInfo); } _animVars.set("rightHandPosition", handPosition); @@ -1414,7 +1515,7 @@ void Rig::updateFromControllerParameters(const ControllerParameters& params, flo updateHands(leftHandEnabled, rightHandEnabled, hipsEnabled, leftArmEnabled, rightArmEnabled, dt, params.primaryControllerPoses[PrimaryControllerType_LeftHand], params.primaryControllerPoses[PrimaryControllerType_RightHand], - params.bodyCapsuleRadius, params.bodyCapsuleHalfHeight, params.bodyCapsuleLocalOffset); + params.hipsShapeInfo, params.spineShapeInfo, params.spine1ShapeInfo, params.spine2ShapeInfo); updateFeet(leftFootEnabled, rightFootEnabled, params.primaryControllerPoses[PrimaryControllerType_LeftFoot], params.primaryControllerPoses[PrimaryControllerType_RightFoot]); diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 7e1504e461..ca55635250 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -75,9 +75,10 @@ public: AnimPose secondaryControllerPoses[NumSecondaryControllerTypes]; // rig space bool secondaryControllerActiveFlags[NumSecondaryControllerTypes]; bool isTalking; - float bodyCapsuleRadius; - float bodyCapsuleHalfHeight; - glm::vec3 bodyCapsuleLocalOffset; + FBXJointShapeInfo hipsShapeInfo; + FBXJointShapeInfo spineShapeInfo; + FBXJointShapeInfo spine1ShapeInfo; + FBXJointShapeInfo spine2ShapeInfo; }; struct EyeParameters { @@ -249,7 +250,8 @@ protected: void updateHead(bool headEnabled, bool hipsEnabled, const AnimPose& headMatrix); void updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnabled, bool leftArmEnabled, bool rightArmEnabled, float dt, const AnimPose& leftHandPose, const AnimPose& rightHandPose, - float bodyCapsuleRadius, float bodyCapsuleHalfHeight, const glm::vec3& bodyCapsuleLocalOffset); + const FBXJointShapeInfo& hipsShapeInfo, const FBXJointShapeInfo& spineShapeInfo, + const FBXJointShapeInfo& spine1ShapeInfo, const FBXJointShapeInfo& spine2ShapeInfo); void updateFeet(bool leftFootEnabled, bool rightFootEnabled, const AnimPose& leftFootPose, const AnimPose& rightFootPose); void updateEyeJoint(int index, const glm::vec3& modelTranslation, const glm::quat& modelRotation, const glm::vec3& lookAt, const glm::vec3& saccade); @@ -257,6 +259,8 @@ protected: glm::vec3 calculateElbowPoleVector(int handIndex, int elbowIndex, int armIndex, int hipsIndex, bool isLeft) const; glm::vec3 calculateKneePoleVector(int footJointIndex, int kneeJoint, int upLegIndex, int hipsIndex, const AnimPose& targetFootPose) const; + glm::vec3 deflectHandFromTorso(const glm::vec3& handPosition, const FBXJointShapeInfo& hipsShapeInfo, const FBXJointShapeInfo& spineShapeInfo, + const FBXJointShapeInfo& spine1ShapeInfo, const FBXJointShapeInfo& spine2ShapeInfo) const; AnimPose _modelOffset; // model to rig space AnimPose _geometryOffset; // geometry to model space (includes unit offset & fst offsets) From b050d2c4c7b81be1b1bf3274561b9d7ce84d030e Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 11 Aug 2017 15:15:43 -0700 Subject: [PATCH 27/54] fix case on include for linux --- libraries/shared/src/GeometryUtil.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/GeometryUtil.cpp b/libraries/shared/src/GeometryUtil.cpp index 0b889e4c24..5f1df59645 100644 --- a/libraries/shared/src/GeometryUtil.cpp +++ b/libraries/shared/src/GeometryUtil.cpp @@ -17,7 +17,7 @@ #include #include "NumericalConstants.h" -#include "glmHelpers.h" +#include "GLMHelpers.h" glm::vec3 computeVectorFromPointToSegment(const glm::vec3& point, const glm::vec3& start, const glm::vec3& end) { // compute the projection of the point vector onto the segment vector From 3bc185e67cefb7fb007442ae306f72c45cf39018 Mon Sep 17 00:00:00 2001 From: Anshuman Dewangan Date: Fri, 11 Aug 2017 15:37:55 -0700 Subject: [PATCH 28/54] Correct desktop icon name --- cmake/macros/SetPackagingParameters.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/macros/SetPackagingParameters.cmake b/cmake/macros/SetPackagingParameters.cmake index cff42971b4..fea244873c 100644 --- a/cmake/macros/SetPackagingParameters.cmake +++ b/cmake/macros/SetPackagingParameters.cmake @@ -118,7 +118,7 @@ macro(SET_PACKAGING_PARAMETERS) set(CONSOLE_SHORTCUT_NAME "Sandbox - ${BUILD_VERSION}") endif () - set(INTERFACE_HF_SHORTCUT_NAME "High Fidelity ${INTERFACE_SHORTCUT_NAME}") + set(INTERFACE_HF_SHORTCUT_NAME "${INTERFACE_SHORTCUT_NAME}") set(CONSOLE_HF_SHORTCUT_NAME "High Fidelity ${CONSOLE_SHORTCUT_NAME}") set(PRE_SANDBOX_INTERFACE_SHORTCUT_NAME "High Fidelity") From 9120e678f1b26c5fda9038d55c54dd5046aba19e Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 11 Aug 2017 16:17:13 -0700 Subject: [PATCH 29/54] Use asynchronous commerce API --- .../resources/qml/hifi/commerce/Checkout.qml | 65 +++++++++---------- .../resources/qml/hifi/commerce/Inventory.qml | 18 ++++- 2 files changed, 46 insertions(+), 37 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/Checkout.qml b/interface/resources/qml/hifi/commerce/Checkout.qml index a0a5af88ab..458e417654 100644 --- a/interface/resources/qml/hifi/commerce/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/Checkout.qml @@ -24,40 +24,43 @@ Rectangle { HifiConstants { id: hifi; } id: checkoutRoot; - property string itemId; - property string itemHref; - property int balanceAfterPurchase: commerce.balance() - parseInt(itemPriceText.text, 10); - property bool alreadyOwned: checkAlreadyOwned(itemId); + property string itemId: ""; + property string itemHref: ""; + property int hfcBalance: 0; + property int balanceAfterPurchase: 0; + property bool alreadyOwned: false; // Style color: hifi.colors.baseGray; Hifi.QmlCommerce { id: commerce; onBuyResult: { - /* - if (buyFailed) { + if (failureMessage.length) { sendToScript({method: 'checkout_cancelClicked', params: itemId}); } else { - var success = commerce.buy(itemId, parseInt(itemPriceText.text)); - sendToScript({method: 'checkout_buyClicked', success: success, itemId: itemId, itemHref: itemHref}); - if (success) { - if (urlHandler.canHandleUrl(itemHref)) { - urlHandler.handleUrl(itemHref); - } + if (urlHandler.canHandleUrl(itemHref)) { + urlHandler.handleUrl(itemHref); } } - */ - - if (failureMessage.length) { - console.log('buy failed', failureMessage); - //fixme sendToScript({method: 'checkout_cancelClicked', params: itemId}); - } else { - console.log('buy ok'); - //fixme sendToScript({method: 'checkout_buyClicked', success: , itemId: itemId, itemHref: itemHref}); - } } - // FIXME: remove these two after testing - onBalanceResult: console.log('balance', balance, failureMessage); - onInventoryResult: console.log('inventory', inventory, failureMessage); + onBalanceResult: { + if (failureMessage.length) { + console.log("Failed to get balance", failureMessage); + } else { + hfcBalance = balance; + balanceAfterPurchase = hfcBalance - parseInt(itemPriceText.text, 10); + } + } + onInventoryResult: { + if (failureMessage.length) { + console.log("Failed to get inventory", failureMessage); + } else { + if (inventory.indexOf(itemId) !== -1) { + alreadyOwned = true; + } else { + alreadyOwned = false; + } + } + } } // @@ -229,7 +232,7 @@ Rectangle { } RalewayRegular { id: hfcBalanceText; - text: commerce.balance(); + text: hfcBalance; // Text size size: hfcBalanceTextLabel.size; // Anchors @@ -397,16 +400,6 @@ Rectangle { // // FUNCTION DEFINITIONS START // - - function checkAlreadyOwned(idToCheck) { - var inventory = commerce.inventory(); - if (inventory.indexOf(idToCheck) !== -1) { - return true; - } else { - return false; - } - } - // // Function Name: fromScript() // @@ -429,6 +422,8 @@ Rectangle { itemPriceText.text = message.params.itemPrice; itemHref = message.params.itemHref; buyButton.buyFailed = false; + commerce.balance(); + commerce.inventory(); break; case 'buyFailed': buyButton.text = "Buy Failed"; diff --git a/interface/resources/qml/hifi/commerce/Inventory.qml b/interface/resources/qml/hifi/commerce/Inventory.qml index 91fa3b9126..7ed43e6f9e 100644 --- a/interface/resources/qml/hifi/commerce/Inventory.qml +++ b/interface/resources/qml/hifi/commerce/Inventory.qml @@ -29,6 +29,20 @@ Rectangle { color: hifi.colors.baseGray; Hifi.QmlCommerce { id: commerce; + onBalanceResult: { + if (failureMessage.length) { + console.log("Failed to get balance", failureMessage); + } else { + hfcBalanceText.text = balance; + } + } + onInventoryResult: { + if (failureMessage.length) { + console.log("Failed to get inventory", failureMessage); + } else { + inventoryContentsList.model = inventory; + } + } } // @@ -101,7 +115,6 @@ Rectangle { } RalewayRegular { id: hfcBalanceText; - text: commerce.balance(); // Text size size: hfcBalanceTextLabel.size; // Anchors @@ -158,7 +171,6 @@ Rectangle { anchors.left: parent.left; anchors.bottom: parent.bottom; width: parent.width; - model: commerce.inventory(); delegate: Item { width: parent.width; height: 30; @@ -247,6 +259,8 @@ Rectangle { switch (message.method) { case 'updateInventory': referrerURL = message.referrerURL; + commerce.balance(); + commerce.inventory(); break; default: console.log('Unrecognized message from marketplaces.js:', JSON.stringify(message)); From c38837c20021bfc5e758f040be8a563a3483545f Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 11 Aug 2017 16:21:39 -0700 Subject: [PATCH 30/54] Remove fixmes --- interface/resources/qml/hifi/commerce/Checkout.qml | 12 ++++-------- scripts/system/marketplaces/marketplaces.js | 8 ++------ 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/Checkout.qml b/interface/resources/qml/hifi/commerce/Checkout.qml index 458e417654..cfa8f82fd9 100644 --- a/interface/resources/qml/hifi/commerce/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/Checkout.qml @@ -35,11 +35,13 @@ Rectangle { id: commerce; onBuyResult: { if (failureMessage.length) { - sendToScript({method: 'checkout_cancelClicked', params: itemId}); + buyButton.text = "Buy Failed"; + buyButton.enabled = false; } else { if (urlHandler.canHandleUrl(itemHref)) { urlHandler.handleUrl(itemHref); } + sendToScript({method: 'checkout_buySuccess', params: itemId}); } } onBalanceResult: { @@ -369,13 +371,12 @@ Rectangle { width: parent.width/2 - anchors.leftMargin*2; text: "Cancel" onClicked: { - sendToScript({method: 'checkout_cancelClicked', params: itemId}); //fixme + sendToScript({method: 'checkout_cancelClicked', params: itemId}); } } // "Buy" button HifiControlsUit.Button { - property bool buyFailed: false; // fixme id: buyButton; enabled: balanceAfterPurchase >= 0 && !alreadyOwned; color: hifi.buttons.black; @@ -421,14 +422,9 @@ Rectangle { itemAuthorText.text = message.params.itemAuthor; itemPriceText.text = message.params.itemPrice; itemHref = message.params.itemHref; - buyButton.buyFailed = false; commerce.balance(); commerce.inventory(); break; - case 'buyFailed': - buyButton.text = "Buy Failed"; - buyButton.buyFailed = true; - break; default: console.log('Unrecognized message from marketplaces.js:', JSON.stringify(message)); } diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index e44e9fda94..9378a1d95b 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -204,12 +204,8 @@ // I don't think this is trivial to do since we also want to inject some JS into the DOM. //tablet.popFromStack(); break; - case 'checkout_buyClicked': - if (message.success === true) { - tablet.gotoWebScreen(MARKETPLACE_URL + '/items/' + message.itemId, MARKETPLACES_INJECT_SCRIPT_URL); - } else { - tablet.sendToQml({ method: 'buyFailed' }); - } + case 'checkout_buySuccess': + tablet.gotoWebScreen(MARKETPLACE_URL + '/items/' + message.itemId, MARKETPLACES_INJECT_SCRIPT_URL); //tablet.popFromStack(); break; case 'inventory_itemClicked': From d8e5f7a067155e5d2c9c8f468b3426e0605bee9a Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 11 Aug 2017 16:28:08 -0700 Subject: [PATCH 31/54] Small improvements --- .../resources/qml/hifi/commerce/Checkout.qml | 15 +++++++++------ .../resources/qml/hifi/commerce/Inventory.qml | 1 + 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/Checkout.qml b/interface/resources/qml/hifi/commerce/Checkout.qml index cfa8f82fd9..e40e2ce67f 100644 --- a/interface/resources/qml/hifi/commerce/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/Checkout.qml @@ -24,9 +24,10 @@ Rectangle { HifiConstants { id: hifi; } id: checkoutRoot; + property bool inventoryReceived: false; + property bool balanceReceived: false; property string itemId: ""; property string itemHref: ""; - property int hfcBalance: 0; property int balanceAfterPurchase: 0; property bool alreadyOwned: false; // Style @@ -48,14 +49,16 @@ Rectangle { if (failureMessage.length) { console.log("Failed to get balance", failureMessage); } else { - hfcBalance = balance; - balanceAfterPurchase = hfcBalance - parseInt(itemPriceText.text, 10); + balanceReceived = true; + hfcBalanceText.text = balance; + balanceAfterPurchase = balance - parseInt(itemPriceText.text, 10); } } onInventoryResult: { if (failureMessage.length) { console.log("Failed to get inventory", failureMessage); } else { + inventoryReceived = true; if (inventory.indexOf(itemId) !== -1) { alreadyOwned = true; } else { @@ -234,7 +237,7 @@ Rectangle { } RalewayRegular { id: hfcBalanceText; - text: hfcBalance; + text: "--"; // Text size size: hfcBalanceTextLabel.size; // Anchors @@ -378,7 +381,7 @@ Rectangle { // "Buy" button HifiControlsUit.Button { id: buyButton; - enabled: balanceAfterPurchase >= 0 && !alreadyOwned; + enabled: balanceAfterPurchase >= 0 && !alreadyOwned && inventoryReceived && balanceReceived; color: hifi.buttons.black; colorScheme: hifi.colorSchemes.dark; anchors.top: parent.top; @@ -388,7 +391,7 @@ Rectangle { anchors.right: parent.right; anchors.rightMargin: 20; width: parent.width/2 - anchors.rightMargin*2; - text: alreadyOwned ? "Already Owned" : "Buy"; + text: (inventoryReceived && balanceReceived) ? (alreadyOwned ? "Already Owned" : "Buy") : "--"; onClicked: { commerce.buy(itemId, parseInt(itemPriceText.text)); } diff --git a/interface/resources/qml/hifi/commerce/Inventory.qml b/interface/resources/qml/hifi/commerce/Inventory.qml index 7ed43e6f9e..a562d00218 100644 --- a/interface/resources/qml/hifi/commerce/Inventory.qml +++ b/interface/resources/qml/hifi/commerce/Inventory.qml @@ -115,6 +115,7 @@ Rectangle { } RalewayRegular { id: hfcBalanceText; + text: "--"; // Text size size: hfcBalanceTextLabel.size; // Anchors From 0835b7b8e6be09ae59af39cbd0aa825e0d46d138 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 11 Aug 2017 16:36:26 -0700 Subject: [PATCH 32/54] Bugfix --- interface/resources/qml/hifi/commerce/Checkout.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/commerce/Checkout.qml b/interface/resources/qml/hifi/commerce/Checkout.qml index e40e2ce67f..7c2d6b56a5 100644 --- a/interface/resources/qml/hifi/commerce/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/Checkout.qml @@ -42,7 +42,7 @@ Rectangle { if (urlHandler.canHandleUrl(itemHref)) { urlHandler.handleUrl(itemHref); } - sendToScript({method: 'checkout_buySuccess', params: itemId}); + sendToScript({method: 'checkout_buySuccess', itemId: itemId}); } } onBalanceResult: { From f72a94e195036e9295b3a1d346463d7c28e88f62 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 11 Aug 2017 17:28:50 -0700 Subject: [PATCH 33/54] warning fixes --- libraries/shared/src/GeometryUtil.cpp | 125 +++++++++++++------------- 1 file changed, 63 insertions(+), 62 deletions(-) diff --git a/libraries/shared/src/GeometryUtil.cpp b/libraries/shared/src/GeometryUtil.cpp index 5f1df59645..6b9718fbb8 100644 --- a/libraries/shared/src/GeometryUtil.cpp +++ b/libraries/shared/src/GeometryUtil.cpp @@ -692,67 +692,68 @@ const glm::vec3 DOP14_NORMALS[DOP14_COUNT] = { -glm::vec3(INV_SQRT_3, -INV_SQRT_3, -INV_SQRT_3) }; +typedef std::tuple Int3Tuple; const std::tuple DOP14_PLANE_COMBINATIONS[] = { - {0,2,4}, {0,2,5}, {0,2,6}, {0,2,7}, {0,2,8}, {0,2,9}, {0,2,10}, {0,2,11}, {0,2,12}, {0,2,13}, - {0,3,4}, {0,3,5}, {0,3,6}, {0,3,7}, {0,3,8}, {0,3,9}, {0,3,10}, {0,3,11}, {0,3,12}, {0,3,13}, - {0,4,6}, {0,4,7}, {0,4,8}, {0,4,9}, {0,4,10}, {0,4,11}, {0,4,12}, {0,4,13}, - {0,5,6}, {0,5,7}, {0,5,8}, {0,5,9}, {0,5,10}, {0,5,11}, {0,5,12}, {0,5,13}, - {0,6,8}, {0,6,9}, {0,6,10}, {0,6,11}, {0,6,12}, {0,6,13}, - {0,7,8}, {0,7,9}, {0,7,10}, {0,7,11}, {0,7,12}, {0,7,13}, - {0,8,10}, {0,8,11}, {0,8,12}, {0,8,13}, {0,9,10}, - {0,9,11}, {0,9,12}, {0,9,13}, - {0,10,12}, {0,10,13}, - {0,11,12}, {0,11,13}, - {1,2,4}, {1,2,5}, {1,2,6}, {1,2,7}, {1,2,8}, {1,2,9}, {1,2,10}, {1,2,11}, {1,2,12}, {1,2,13}, - {1,3,4}, {1,3,5}, {1,3,6}, {1,3,7}, {1,3,8}, {1,3,9}, {1,3,10}, {1,3,11}, {1,3,12}, {1,3,13}, - {1,4,6}, {1,4,7}, {1,4,8}, {1,4,9}, {1,4,10}, {1,4,11}, {1,4,12}, {1,4,13}, - {1,5,6}, {1,5,7}, {1,5,8}, {1,5,9}, {1,5,10}, {1,5,11}, {1,5,12}, {1,5,13}, - {1,6,8}, {1,6,9}, {1,6,10}, {1,6,11}, {1,6,12}, {1,6,13}, - {1,7,8}, {1,7,9}, {1,7,10}, {1,7,11}, {1,7,12}, {1,7,13}, - {1,8,10}, {1,8,11}, {1,8,12}, {1,8,13}, - {1,9,10}, {1,9,11}, {1,9,12}, {1,9,13}, - {1,10,12}, {1,10,13}, - {1,11,12}, {1,11,13}, - {2,4,6}, {2,4,7}, {2,4,8}, {2,4,9}, {2,4,10}, {2,4,11}, {2,4,12}, {2,4,13}, - {2,5,6}, {2,5,7}, {2,5,8}, {2,5,9}, {2,5,10}, {2,5,11}, {2,5,12}, {2,5,13}, - {2,6,8}, {2,6,9}, {2,6,10}, {2,6,11}, {2,6,12}, {2,6,13}, - {2,7,8}, {2,7,9}, {2,7,10}, {2,7,11}, {2,7,12}, {2,7,13}, - {2,8,10}, {2,8,11}, {2,8,12}, {2,8,13}, - {2,9,10}, {2,9,11}, {2,9,12}, {2,9,13}, - {2,10,12}, {2,10,13}, - {2,11,12}, {2,11,13}, - {3,4,6}, {3,4,7}, {3,4,8}, {3,4,9}, {3,4,10}, {3,4,11}, {3,4,12}, {3,4,13}, - {3,5,6}, {3,5,7}, {3,5,8}, {3,5,9}, {3,5,10}, {3,5,11}, {3,5,12}, {3,5,13}, - {3,6,8}, {3,6,9}, {3,6,10}, {3,6,11}, {3,6,12}, {3,6,13}, - {3,7,8}, {3,7,9}, {3,7,10}, {3,7,11}, {3,7,12}, {3,7,13}, - {3,8,10}, {3,8,11}, {3,8,12}, {3,8,13}, - {3,9,10}, {3,9,11}, {3,9,12}, {3,9,13}, - {3,10,12}, {3,10,13}, - {3,11,12}, {3,11,13}, - {4,6,8}, {4,6,9}, {4,6,10}, {4,6,11}, {4,6,12}, {4,6,13}, - {4,7,8}, {4,7,9}, {4,7,10}, {4,7,11}, {4,7,12}, {4,7,13}, - {4,8,10}, {4,8,11}, {4,8,12}, {4,8,13}, - {4,9,10}, {4,9,11}, {4,9,12}, {4,9,13}, - {4,10,12}, {4,10,13}, - {4,11,12}, {4,11,13}, - {5,6,8}, {5,6,9}, {5,6,10}, {5,6,11}, {5,6,12}, {5,6,13}, - {5,7,8}, {5,7,9}, {5,7,10}, {5,7,11}, {5,7,12}, {5,7,13}, - {5,8,10}, {5,8,11}, {5,8,12}, {5,8,13}, - {5,9,10}, {5,9,11}, {5,9,12}, {5,9,13}, - {5,10,12}, {5,10,13}, - {5,11,12}, {5,11,13}, - {6,8,10}, {6,8,11}, {6,8,12}, {6,8,13}, - {6,9,10}, {6,9,11}, {6,9,12}, {6,9,13}, - {6,10,12}, {6,10,13}, - {6,11,12}, {6,11,13}, - {7,8,10}, {7,8,11}, {7,8,12}, {7,8,13}, - {7,9,10}, {7,9,11}, {7,9,12}, {7,9,13}, - {7,10,12}, {7,10,13}, - {7,11,12}, {7,11,13}, - {8,10,12}, {8,10,13}, - {8,11,12}, {8,11,13}, - {9,10,12}, {9,10,13}, - {9,11,12}, {9,11,13} + Int3Tuple(0, 2, 4), Int3Tuple(0, 2, 5), Int3Tuple(0, 2, 6), Int3Tuple(0, 2, 7), Int3Tuple(0, 2, 8), Int3Tuple(0, 2, 9), Int3Tuple(0, 2, 10), Int3Tuple(0, 2, 11), Int3Tuple(0, 2, 12), Int3Tuple(0, 2, 13), + Int3Tuple(0, 3, 4), Int3Tuple(0, 3, 5), Int3Tuple(0, 3, 6), Int3Tuple(0, 3, 7), Int3Tuple(0, 3, 8), Int3Tuple(0, 3, 9), Int3Tuple(0, 3, 10), Int3Tuple(0, 3, 11), Int3Tuple(0, 3, 12), Int3Tuple(0, 3, 13), + Int3Tuple(0, 4, 6), Int3Tuple(0, 4, 7), Int3Tuple(0, 4, 8), Int3Tuple(0, 4, 9), Int3Tuple(0, 4, 10), Int3Tuple(0, 4, 11), Int3Tuple(0, 4, 12), Int3Tuple(0, 4, 13), + Int3Tuple(0, 5, 6), Int3Tuple(0, 5, 7), Int3Tuple(0, 5, 8), Int3Tuple(0, 5, 9), Int3Tuple(0, 5, 10), Int3Tuple(0, 5, 11), Int3Tuple(0, 5, 12), Int3Tuple(0, 5, 13), + Int3Tuple(0, 6, 8), Int3Tuple(0, 6, 9), Int3Tuple(0, 6, 10), Int3Tuple(0, 6, 11), Int3Tuple(0, 6, 12), Int3Tuple(0, 6, 13), + Int3Tuple(0, 7, 8), Int3Tuple(0, 7, 9), Int3Tuple(0, 7, 10), Int3Tuple(0, 7, 11), Int3Tuple(0, 7, 12), Int3Tuple(0, 7, 13), + Int3Tuple(0, 8, 10), Int3Tuple(0, 8, 11), Int3Tuple(0, 8, 12), Int3Tuple(0, 8, 13), Int3Tuple(0, 9, 10), + Int3Tuple(0, 9, 11), Int3Tuple(0, 9, 12), Int3Tuple(0, 9, 13), + Int3Tuple(0, 10, 12), Int3Tuple(0, 10, 13), + Int3Tuple(0, 11, 12), Int3Tuple(0, 11, 13), + Int3Tuple(1, 2, 4), Int3Tuple(1, 2, 5), Int3Tuple(1, 2, 6), Int3Tuple(1, 2, 7), Int3Tuple(1, 2, 8), Int3Tuple(1, 2, 9), Int3Tuple(1, 2, 10), Int3Tuple(1, 2, 11), Int3Tuple(1, 2, 12), Int3Tuple(1, 2, 13), + Int3Tuple(1, 3, 4), Int3Tuple(1, 3, 5), Int3Tuple(1, 3, 6), Int3Tuple(1, 3, 7), Int3Tuple(1, 3, 8), Int3Tuple(1, 3, 9), Int3Tuple(1, 3, 10), Int3Tuple(1, 3, 11), Int3Tuple(1, 3, 12), Int3Tuple(1, 3, 13), + Int3Tuple(1, 4, 6), Int3Tuple(1, 4, 7), Int3Tuple(1, 4, 8), Int3Tuple(1, 4, 9), Int3Tuple(1, 4, 10), Int3Tuple(1, 4, 11), Int3Tuple(1, 4, 12), Int3Tuple(1, 4, 13), + Int3Tuple(1, 5, 6), Int3Tuple(1, 5, 7), Int3Tuple(1, 5, 8), Int3Tuple(1, 5, 9), Int3Tuple(1, 5, 10), Int3Tuple(1, 5, 11), Int3Tuple(1, 5, 12), Int3Tuple(1, 5, 13), + Int3Tuple(1, 6, 8), Int3Tuple(1, 6, 9), Int3Tuple(1, 6, 10), Int3Tuple(1, 6, 11), Int3Tuple(1, 6, 12), Int3Tuple(1, 6, 13), + Int3Tuple(1, 7, 8), Int3Tuple(1, 7, 9), Int3Tuple(1, 7, 10), Int3Tuple(1, 7, 11), Int3Tuple(1, 7, 12), Int3Tuple(1, 7, 13), + Int3Tuple(1, 8, 10), Int3Tuple(1, 8, 11), Int3Tuple(1, 8, 12), Int3Tuple(1, 8, 13), + Int3Tuple(1, 9, 10), Int3Tuple(1, 9, 11), Int3Tuple(1, 9, 12), Int3Tuple(1, 9, 13), + Int3Tuple(1, 10, 12), Int3Tuple(1, 10, 13), + Int3Tuple(1, 11, 12), Int3Tuple(1, 11, 13), + Int3Tuple(2, 4, 6), Int3Tuple(2, 4, 7), Int3Tuple(2, 4, 8), Int3Tuple(2, 4, 9), Int3Tuple(2, 4, 10), Int3Tuple(2, 4, 11), Int3Tuple(2, 4, 12), Int3Tuple(2, 4, 13), + Int3Tuple(2, 5, 6), Int3Tuple(2, 5, 7), Int3Tuple(2, 5, 8), Int3Tuple(2, 5, 9), Int3Tuple(2, 5, 10), Int3Tuple(2, 5, 11), Int3Tuple(2, 5, 12), Int3Tuple(2, 5, 13), + Int3Tuple(2, 6, 8), Int3Tuple(2, 6, 9), Int3Tuple(2, 6, 10), Int3Tuple(2, 6, 11), Int3Tuple(2, 6, 12), Int3Tuple(2, 6, 13), + Int3Tuple(2, 7, 8), Int3Tuple(2, 7, 9), Int3Tuple(2, 7, 10), Int3Tuple(2, 7, 11), Int3Tuple(2, 7, 12), Int3Tuple(2, 7, 13), + Int3Tuple(2, 8, 10), Int3Tuple(2, 8, 11), Int3Tuple(2, 8, 12), Int3Tuple(2, 8, 13), + Int3Tuple(2, 9, 10), Int3Tuple(2, 9, 11), Int3Tuple(2, 9, 12), Int3Tuple(2, 9, 13), + Int3Tuple(2, 10, 12), Int3Tuple(2, 10, 13), + Int3Tuple(2, 11, 12), Int3Tuple(2, 11, 13), + Int3Tuple(3, 4, 6), Int3Tuple(3, 4, 7), Int3Tuple(3, 4, 8), Int3Tuple(3, 4, 9), Int3Tuple(3, 4, 10), Int3Tuple(3, 4, 11), Int3Tuple(3, 4, 12), Int3Tuple(3, 4, 13), + Int3Tuple(3, 5, 6), Int3Tuple(3, 5, 7), Int3Tuple(3, 5, 8), Int3Tuple(3, 5, 9), Int3Tuple(3, 5, 10), Int3Tuple(3, 5, 11), Int3Tuple(3, 5, 12), Int3Tuple(3, 5, 13), + Int3Tuple(3, 6, 8), Int3Tuple(3, 6, 9), Int3Tuple(3, 6, 10), Int3Tuple(3, 6, 11), Int3Tuple(3, 6, 12), Int3Tuple(3, 6, 13), + Int3Tuple(3, 7, 8), Int3Tuple(3, 7, 9), Int3Tuple(3, 7, 10), Int3Tuple(3, 7, 11), Int3Tuple(3, 7, 12), Int3Tuple(3, 7, 13), + Int3Tuple(3, 8, 10), Int3Tuple(3, 8, 11), Int3Tuple(3, 8, 12), Int3Tuple(3, 8, 13), + Int3Tuple(3, 9, 10), Int3Tuple(3, 9, 11), Int3Tuple(3, 9, 12), Int3Tuple(3, 9, 13), + Int3Tuple(3, 10, 12), Int3Tuple(3, 10, 13), + Int3Tuple(3, 11, 12), Int3Tuple(3, 11, 13), + Int3Tuple(4, 6, 8), Int3Tuple(4, 6, 9), Int3Tuple(4, 6, 10), Int3Tuple(4, 6, 11), Int3Tuple(4, 6, 12), Int3Tuple(4, 6, 13), + Int3Tuple(4, 7, 8), Int3Tuple(4, 7, 9), Int3Tuple(4, 7, 10), Int3Tuple(4, 7, 11), Int3Tuple(4, 7, 12), Int3Tuple(4, 7, 13), + Int3Tuple(4, 8, 10), Int3Tuple(4, 8, 11), Int3Tuple(4, 8, 12), Int3Tuple(4, 8, 13), + Int3Tuple(4, 9, 10), Int3Tuple(4, 9, 11), Int3Tuple(4, 9, 12), Int3Tuple(4, 9, 13), + Int3Tuple(4, 10, 12), Int3Tuple(4, 10, 13), + Int3Tuple(4, 11, 12), Int3Tuple(4, 11, 13), + Int3Tuple(5, 6, 8), Int3Tuple(5, 6, 9), Int3Tuple(5, 6, 10), Int3Tuple(5, 6, 11), Int3Tuple(5, 6, 12), Int3Tuple(5, 6, 13), + Int3Tuple(5, 7, 8), Int3Tuple(5, 7, 9), Int3Tuple(5, 7, 10), Int3Tuple(5, 7, 11), Int3Tuple(5, 7, 12), Int3Tuple(5, 7, 13), + Int3Tuple(5, 8, 10), Int3Tuple(5, 8, 11), Int3Tuple(5, 8, 12), Int3Tuple(5, 8, 13), + Int3Tuple(5, 9, 10), Int3Tuple(5, 9, 11), Int3Tuple(5, 9, 12), Int3Tuple(5, 9, 13), + Int3Tuple(5, 10, 12), Int3Tuple(5, 10, 13), + Int3Tuple(5, 11, 12), Int3Tuple(5, 11, 13), + Int3Tuple(6, 8, 10), Int3Tuple(6, 8, 11), Int3Tuple(6, 8, 12), Int3Tuple(6, 8, 13), + Int3Tuple(6, 9, 10), Int3Tuple(6, 9, 11), Int3Tuple(6, 9, 12), Int3Tuple(6, 9, 13), + Int3Tuple(6, 10, 12), Int3Tuple(6, 10, 13), + Int3Tuple(6, 11, 12), Int3Tuple(6, 11, 13), + Int3Tuple(7, 8, 10), Int3Tuple(7, 8, 11), Int3Tuple(7, 8, 12), Int3Tuple(7, 8, 13), + Int3Tuple(7, 9, 10), Int3Tuple(7, 9, 11), Int3Tuple(7, 9, 12), Int3Tuple(7, 9, 13), + Int3Tuple(7, 10, 12), Int3Tuple(7, 10, 13), + Int3Tuple(7, 11, 12), Int3Tuple(7, 11, 13), + Int3Tuple(8, 10, 12), Int3Tuple(8, 10, 13), + Int3Tuple(8, 11, 12), Int3Tuple(8, 11, 13), + Int3Tuple(9, 10, 12), Int3Tuple(9, 10, 13), + Int3Tuple(9, 11, 12), Int3Tuple(9, 11, 13) }; void generateBoundryLinesForDop14(const std::vector& dots, const glm::vec3& center, std::vector& linesOut) { @@ -786,8 +787,8 @@ void generateBoundryLinesForDop14(const std::vector& dots, const glm::vec } // build a set of lines between these vertices, that also lie on the surface of the k-dop. - for (int i = 0; i < vertices.size(); i++) { - for (int j = i; j < vertices.size(); j++) { + for (size_t i = 0; i < vertices.size(); i++) { + for (size_t j = i; j < vertices.size(); j++) { glm::vec3 midPoint = (vertices[i] + vertices[j]) * 0.5f; int onSurfaceCount = 0; const float SURFACE_MARGIN = 0.01f; From 8c9f3ae9775d15101b2b6f966f6a4195c651dc58 Mon Sep 17 00:00:00 2001 From: Cain Kilgore Date: Sat, 12 Aug 2017 01:35:48 +0100 Subject: [PATCH 34/54] Skybox Changer PR --- .../resources/qml/hifi/SkyboxChanger.qml | 184 ++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 interface/resources/qml/hifi/SkyboxChanger.qml diff --git a/interface/resources/qml/hifi/SkyboxChanger.qml b/interface/resources/qml/hifi/SkyboxChanger.qml new file mode 100644 index 0000000000..9d7fc39157 --- /dev/null +++ b/interface/resources/qml/hifi/SkyboxChanger.qml @@ -0,0 +1,184 @@ +// +// skyboxchanger.qml +// +// +// Created by Cain Kilgore on 9th August 2017 +// Copyright 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 +// + +import QtQuick 2.5 +import QtQuick.Controls 1.5 as QQControls +import QtQuick.Layouts 1.3 +import QtQuick.Controls.Styles 1.4 + +import QtWebEngine 1.2 +import QtWebChannel 1.0 + +import "../styles-uit" +import "../controls-uit" as HifiControls +import "../windows" +import "../controls" + +Rectangle { + id: root; + + HifiConstants { id: hifi; } + + property string title: ""; + + color: hifi.colors.baseGray; + + Item { + id: titleBarContainer; + // Size + width: parent.width; + height: 50; + // Anchors + anchors.left: parent.left; + anchors.top: parent.top; + + RalewaySemiBold { + id: titleBarText; + text: "Skybox Changer"; + // Text size + size: hifi.fontSizes.overlayTitle; + // Anchors + anchors.fill: parent; + anchors.leftMargin: 16; + // Style + color: hifi.colors.lightGrayText; + // Alignment + horizontalAlignment: Text.AlignHCenter; + verticalAlignment: Text.AlignVCenter; + } + RalewaySemiBold { + id: titleBarDesc; + text: "You can set the current Skybox of the Zone you're standing in by clicking on any of the 6 pre-determined skyboxes below."; + wrapMode: Text.Wrap + // Text size + size: 14; + // Anchors + anchors.fill: parent; + anchors.topMargin: 56; + anchors.leftMargin: 16; + anchors.rightMargin: 16; + // Style + color: hifi.colors.lightGrayText; + // Alignment + horizontalAlignment: Text.AlignHCenter; + verticalAlignment: Text.AlignVCenter; + } + } + RowLayout { + id: row1 + anchors.top: titleBarContainer.bottom + anchors.left: parent.left + anchors.leftMargin: 30 + Layout.fillWidth: true + anchors.topMargin: 30 + spacing: 10 + Image { + width: 200; height: 200 + fillMode: Image.Stretch + source: "http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/thumbnails/thumb_1.jpg" + clip: true + id: preview1 + MouseArea { + anchors.fill: parent + onClicked: { + sendToScript({method: 'changeSkybox', url: 'http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/skyboxes/1.jpg'}); + } + } + Layout.fillWidth: true + } + Image { + width: 200; height: 200 + fillMode: Image.Stretch + source: "http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/thumbnails/thumb_2.jpg" + clip: true + id: preview2 + MouseArea { + anchors.fill: parent + onClicked: { + sendToScript({method: 'changeSkybox', url: 'http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/skyboxes/2.png'}); + } + } + } + } + RowLayout { + id: row2 + anchors.top: row1.bottom + anchors.topMargin: 10 + anchors.left: parent.left + Layout.fillWidth: true + anchors.leftMargin: 30 + spacing: 10 + Image { + width: 200; height: 200 + fillMode: Image.Stretch + source: "http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/thumbnails/thumb_3.jpg" + clip: true + id: preview3 + MouseArea { + anchors.fill: parent + onClicked: { + sendToScript({method: 'changeSkybox', url: 'http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/skyboxes/3.jpg'}); + } + } + } + Image { + width: 200; height: 200 + fillMode: Image.Stretch + source: "http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/thumbnails/thumb_4.jpg" + clip: true + id: preview4 + MouseArea { + anchors.fill: parent + onClicked: { + sendToScript({method: 'changeSkybox', url: 'http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/skyboxes/4.jpg'}); + } + } + } + } + RowLayout { + id: row3 + anchors.top: row2.bottom + anchors.topMargin: 10 + anchors.left: parent.left + Layout.fillWidth: true + anchors.leftMargin: 30 + spacing: 10 + Image { + width: 200; height: 200 + fillMode: Image.Stretch + source: "http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/thumbnails/thumb_5.jpg" + clip: true + id: preview5 + MouseArea { + anchors.fill: parent + onClicked: { + sendToScript({method: 'changeSkybox', url: 'http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/skyboxes/5.png'}); + } + } + } + Image { + width: 200; height: 200 + fillMode: Image.Stretch + source: "http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/thumbnails/thumb_6.jpg" + clip: true + id: preview6 + MouseArea { + anchors.fill: parent + onClicked: { + sendToScript({method: 'changeSkybox', url: 'http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/skyboxes/6.jpg'}); + } + } + } + } + + signal sendToScript(var message); + +} From cd57c0706a785943212b09a159121aab26d73598 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 11 Aug 2017 17:46:50 -0700 Subject: [PATCH 35/54] more warning fixes --- interface/src/avatar/MyAvatar.cpp | 2 +- libraries/animation/src/Rig.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 3048d04247..2109aa7dfa 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1831,7 +1831,7 @@ void MyAvatar::postUpdate(float deltaTime) { rig.getAbsoluteJointPoseInRigFrame(i, jointPose); const FBXJointShapeInfo& shapeInfo = geometry.joints[i].shapeInfo; const AnimPose pose = rigToWorldPose * jointPose; - for (int j = 0; j < shapeInfo.debugLines.size() / 2; j++) { + for (size_t j = 0; j < shapeInfo.debugLines.size() / 2; j++) { glm::vec3 pointA = pose.xformPoint(shapeInfo.debugLines[2 * j]); glm::vec3 pointB = pose.xformPoint(shapeInfo.debugLines[2 * j + 1]); DebugDraw::getInstance().drawRay(pointA, pointB, DEBUG_COLORS[i % NUM_DEBUG_COLORS]); diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 15886a1212..e01624655b 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1831,7 +1831,7 @@ void Rig::computeAvatarBoundingCapsule( const FBXJointShapeInfo& shapeInfo = geometry.joints.at(index).shapeInfo; AnimPose pose = finalPoses[index]; if (shapeInfo.points.size() > 0) { - for (int j = 0; j < shapeInfo.points.size(); ++j) { + for (size_t j = 0; j < shapeInfo.points.size(); ++j) { totalExtents.addPoint((pose * shapeInfo.points[j])); } } From ff98dedbb289e99eb2f96389c17e3ac0dfca11d5 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 11 Aug 2017 18:10:44 -0700 Subject: [PATCH 36/54] Debugging the graphics fields activation --- interface/resources/config/render.json | 16 +++++++++++++- interface/src/Application.cpp | 2 +- interface/src/ui/PreferencesDialog.cpp | 22 ++++++++++--------- .../spectator-camera/spectatorCamera.js | 2 +- 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/interface/resources/config/render.json b/interface/resources/config/render.json index b5b72d7d07..5266ee0666 100644 --- a/interface/resources/config/render.json +++ b/interface/resources/config/render.json @@ -1,4 +1,18 @@ { + "SecondaryCameraJob": { + "RenderShadowTask": { + "Enabled": { + "enabled": true + } + }, + "RenderDeferredTask": { + "AmbientOcclusion": { + "Enabled": { + "enabled": true + } + } + } + }, "RenderMainView": { "RenderShadowTask": { "Enabled": { @@ -13,4 +27,4 @@ } } } -} +} \ No newline at end of file diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3d7df0d579..5299ab5b3f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -351,7 +351,7 @@ public: // Don't actually crash in debug builds, in case this apparent deadlock is simply from // the developer actively debugging code #ifdef NDEBUG - deadlockDetectionCrash(); + // deadlockDetectionCrash(); #endif } } diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index c9e59ada23..35184a391d 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -315,21 +315,23 @@ void setupPreferences() { static const QString RENDER("Graphics"); auto renderConfig = qApp->getRenderEngine()->getConfiguration(); if (renderConfig) { - auto ambientOcclusionConfig = renderConfig->getConfig(); - if (ambientOcclusionConfig) { - auto getter = [ambientOcclusionConfig]()->QString { return ambientOcclusionConfig->getPreset(); }; - auto setter = [ambientOcclusionConfig](QString preset) { ambientOcclusionConfig->setPreset(preset); }; + auto mainViewAmbientOcclusionConfig = renderConfig->getConfig("RenderMainView.AmbientOcclusion"); + auto camViewAmbientOcclusionConfig = renderConfig->getConfig("SecondaryCameraJob.AmbientOcclusion"); + if (mainViewAmbientOcclusionConfig && camViewAmbientOcclusionConfig) { + auto getter = [mainViewAmbientOcclusionConfig]()->QString { return mainViewAmbientOcclusionConfig->getPreset(); }; + auto setter = [mainViewAmbientOcclusionConfig, camViewAmbientOcclusionConfig](QString preset) { mainViewAmbientOcclusionConfig->setPreset(preset); camViewAmbientOcclusionConfig->setPreset(preset); }; auto preference = new ComboBoxPreference(RENDER, "Ambient occlusion", getter, setter); - preference->setItems(ambientOcclusionConfig->getPresetList()); + preference->setItems(mainViewAmbientOcclusionConfig->getPresetList()); preferences->addPreference(preference); } - auto shadowConfig = renderConfig->getConfig(); - if (shadowConfig) { - auto getter = [shadowConfig]()->QString { return shadowConfig->getPreset(); }; - auto setter = [shadowConfig](QString preset) { shadowConfig->setPreset(preset); }; + auto mainViewShadowConfig = renderConfig->getConfig("RenderMainView.RenderShadowTask"); + auto camViewShadowConfig = renderConfig->getConfig("SecondaryCameraJob.RenderShadowTask"); + if (mainViewShadowConfig && camViewShadowConfig) { + auto getter = [mainViewShadowConfig]()->QString { return mainViewShadowConfig->getPreset(); }; + auto setter = [mainViewShadowConfig, camViewShadowConfig](QString preset) { mainViewShadowConfig->setPreset(preset); camViewShadowConfig->setPreset(preset); }; auto preference = new ComboBoxPreference(RENDER, "Shadows", getter, setter); - preference->setItems(shadowConfig->getPresetList()); + preference->setItems(mainViewShadowConfig->getPresetList()); preferences->addPreference(preference); } } diff --git a/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.js b/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.js index f0b943ad92..fd08cd5655 100644 --- a/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.js +++ b/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.js @@ -153,7 +153,7 @@ // -showSpectatorInDesktop: Set to "true" to show the "SPECTATOR" app in desktop mode. var button = false; var buttonName = "SPECTATOR"; - var showSpectatorInDesktop = false; + var showSpectatorInDesktop = true; function addOrRemoveButton(isShuttingDown, isHMDMode) { if (!tablet) { print("Warning in addOrRemoveButton(): 'tablet' undefined!"); From 185c8da491bb790be50af33aba73d388b9587264 Mon Sep 17 00:00:00 2001 From: Cain Kilgore Date: Sat, 12 Aug 2017 18:52:54 +0100 Subject: [PATCH 37/54] Changed 6 to six, cause wording. No functionality changes. --- interface/resources/qml/hifi/SkyboxChanger.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/SkyboxChanger.qml b/interface/resources/qml/hifi/SkyboxChanger.qml index 9d7fc39157..a677af2f07 100644 --- a/interface/resources/qml/hifi/SkyboxChanger.qml +++ b/interface/resources/qml/hifi/SkyboxChanger.qml @@ -56,7 +56,7 @@ Rectangle { } RalewaySemiBold { id: titleBarDesc; - text: "You can set the current Skybox of the Zone you're standing in by clicking on any of the 6 pre-determined skyboxes below."; + text: "You can set the current Skybox of the Zone you're standing in by clicking on any of the six pre-determined skyboxes below."; wrapMode: Text.Wrap // Text size size: 14; From 28c81534c4ff18d8a832fb7ae6cb34147873c7cb Mon Sep 17 00:00:00 2001 From: Cain Kilgore Date: Mon, 14 Aug 2017 05:11:53 +0100 Subject: [PATCH 38/54] Updated Text at Top --- interface/resources/qml/hifi/SkyboxChanger.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/SkyboxChanger.qml b/interface/resources/qml/hifi/SkyboxChanger.qml index 9d7fc39157..6291a1c103 100644 --- a/interface/resources/qml/hifi/SkyboxChanger.qml +++ b/interface/resources/qml/hifi/SkyboxChanger.qml @@ -56,7 +56,7 @@ Rectangle { } RalewaySemiBold { id: titleBarDesc; - text: "You can set the current Skybox of the Zone you're standing in by clicking on any of the 6 pre-determined skyboxes below."; + text: "Click an image to choose a new Skybox."; wrapMode: Text.Wrap // Text size size: 14; From 05b78b0df06b6962a2e32c09083923f74beee323 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 14 Aug 2017 10:46:33 -0700 Subject: [PATCH 39/54] Just fixing the ao combo box field --- interface/resources/config/render.json | 14 -------------- interface/src/ui/PreferencesDialog.cpp | 10 ++++------ 2 files changed, 4 insertions(+), 20 deletions(-) diff --git a/interface/resources/config/render.json b/interface/resources/config/render.json index 5266ee0666..83477fef69 100644 --- a/interface/resources/config/render.json +++ b/interface/resources/config/render.json @@ -1,18 +1,4 @@ { - "SecondaryCameraJob": { - "RenderShadowTask": { - "Enabled": { - "enabled": true - } - }, - "RenderDeferredTask": { - "AmbientOcclusion": { - "Enabled": { - "enabled": true - } - } - } - }, "RenderMainView": { "RenderShadowTask": { "Enabled": { diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 35184a391d..88b26a1b8c 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -316,20 +316,18 @@ void setupPreferences() { auto renderConfig = qApp->getRenderEngine()->getConfiguration(); if (renderConfig) { auto mainViewAmbientOcclusionConfig = renderConfig->getConfig("RenderMainView.AmbientOcclusion"); - auto camViewAmbientOcclusionConfig = renderConfig->getConfig("SecondaryCameraJob.AmbientOcclusion"); - if (mainViewAmbientOcclusionConfig && camViewAmbientOcclusionConfig) { + if (mainViewAmbientOcclusionConfig) { auto getter = [mainViewAmbientOcclusionConfig]()->QString { return mainViewAmbientOcclusionConfig->getPreset(); }; - auto setter = [mainViewAmbientOcclusionConfig, camViewAmbientOcclusionConfig](QString preset) { mainViewAmbientOcclusionConfig->setPreset(preset); camViewAmbientOcclusionConfig->setPreset(preset); }; + auto setter = [mainViewAmbientOcclusionConfig](QString preset) { mainViewAmbientOcclusionConfig->setPreset(preset); }; auto preference = new ComboBoxPreference(RENDER, "Ambient occlusion", getter, setter); preference->setItems(mainViewAmbientOcclusionConfig->getPresetList()); preferences->addPreference(preference); } auto mainViewShadowConfig = renderConfig->getConfig("RenderMainView.RenderShadowTask"); - auto camViewShadowConfig = renderConfig->getConfig("SecondaryCameraJob.RenderShadowTask"); - if (mainViewShadowConfig && camViewShadowConfig) { + if (mainViewShadowConfig) { auto getter = [mainViewShadowConfig]()->QString { return mainViewShadowConfig->getPreset(); }; - auto setter = [mainViewShadowConfig, camViewShadowConfig](QString preset) { mainViewShadowConfig->setPreset(preset); camViewShadowConfig->setPreset(preset); }; + auto setter = [mainViewShadowConfig](QString preset) { mainViewShadowConfig->setPreset(preset); }; auto preference = new ComboBoxPreference(RENDER, "Shadows", getter, setter); preference->setItems(mainViewShadowConfig->getPresetList()); preferences->addPreference(preference); From db1536c521a138799457b01bda1fac23bfff6065 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 14 Aug 2017 10:47:58 -0700 Subject: [PATCH 40/54] Reactivate watch dog exit --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5299ab5b3f..3d7df0d579 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -351,7 +351,7 @@ public: // Don't actually crash in debug builds, in case this apparent deadlock is simply from // the developer actively debugging code #ifdef NDEBUG - // deadlockDetectionCrash(); + deadlockDetectionCrash(); #endif } } From 465e390f7b8eed76e4f3f78df3d8bc486133c4d5 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 14 Aug 2017 10:49:08 -0700 Subject: [PATCH 41/54] Redisable spectator cam from desktop --- .../marketplace/spectator-camera/spectatorCamera.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.js b/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.js index fd08cd5655..f0b943ad92 100644 --- a/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.js +++ b/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.js @@ -153,7 +153,7 @@ // -showSpectatorInDesktop: Set to "true" to show the "SPECTATOR" app in desktop mode. var button = false; var buttonName = "SPECTATOR"; - var showSpectatorInDesktop = true; + var showSpectatorInDesktop = false; function addOrRemoveButton(isShuttingDown, isHMDMode) { if (!tablet) { print("Warning in addOrRemoveButton(): 'tablet' undefined!"); From f86f22309b6eede3425303c1d0a1b09a78337994 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 14 Aug 2017 11:31:40 -0700 Subject: [PATCH 42/54] fix render.json --- interface/resources/config/render.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/config/render.json b/interface/resources/config/render.json index 83477fef69..b5b72d7d07 100644 --- a/interface/resources/config/render.json +++ b/interface/resources/config/render.json @@ -13,4 +13,4 @@ } } } -} \ No newline at end of file +} From 199ba3bff0312f874733709e0e44f2a5e26c3902 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 14 Aug 2017 11:55:21 -0700 Subject: [PATCH 43/54] Use new JSON inventory format --- interface/resources/qml/hifi/commerce/Checkout.qml | 11 ++++++++++- interface/resources/qml/hifi/commerce/Inventory.qml | 6 +++--- interface/src/commerce/Ledger.cpp | 13 ++++++++++--- interface/src/commerce/Ledger.h | 6 ++++-- interface/src/commerce/QmlCommerce.h | 2 +- 5 files changed, 28 insertions(+), 10 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/Checkout.qml b/interface/resources/qml/hifi/commerce/Checkout.qml index 7c2d6b56a5..865bb72921 100644 --- a/interface/resources/qml/hifi/commerce/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/Checkout.qml @@ -59,7 +59,7 @@ Rectangle { console.log("Failed to get inventory", failureMessage); } else { inventoryReceived = true; - if (inventory.indexOf(itemId) !== -1) { + if (inventoryContains(inventory.assets, itemId)) { alreadyOwned = true; } else { alreadyOwned = false; @@ -434,6 +434,15 @@ Rectangle { } signal sendToScript(var message); + function inventoryContains(inventoryJson, id) { + for (var idx = 0; idx < inventoryJson.length; idx++) { + if(inventoryJson[idx].id === id) { + return true; + } + } + return false; + } + // // FUNCTION DEFINITIONS END // diff --git a/interface/resources/qml/hifi/commerce/Inventory.qml b/interface/resources/qml/hifi/commerce/Inventory.qml index a562d00218..298abebdab 100644 --- a/interface/resources/qml/hifi/commerce/Inventory.qml +++ b/interface/resources/qml/hifi/commerce/Inventory.qml @@ -40,7 +40,7 @@ Rectangle { if (failureMessage.length) { console.log("Failed to get inventory", failureMessage); } else { - inventoryContentsList.model = inventory; + inventoryContentsList.model = inventory.assets; } } } @@ -181,7 +181,7 @@ Rectangle { size: 20; // Style color: hifi.colors.blueAccent; - text: modelData; + text: modelData.title; // Alignment horizontalAlignment: Text.AlignHLeft; } @@ -189,7 +189,7 @@ Rectangle { anchors.fill: parent; hoverEnabled: enabled; onClicked: { - sendToScript({method: 'inventory_itemClicked', itemId: thisItemId.text}); + sendToScript({method: 'inventory_itemClicked', itemId: modelData.id}); } onEntered: { thisItemId.color = hifi.colors.blueHighlight; diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index b8f9277a2a..ad79a836ad 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -44,7 +44,11 @@ void Ledger::buy(const QString& hfc_key, int cost, const QString& asset_id, cons return emit buyResult("Insufficient funds."); } _balance -= cost; - _inventory.push_back(asset_id); + QJsonObject inventoryAdditionObject; + inventoryAdditionObject["id"] = asset_id; + inventoryAdditionObject["title"] = "Test Title"; + inventoryAdditionObject["preview"] = "https://www.aspca.org/sites/default/files/cat-care_cat-nutrition-tips_overweight_body4_left.jpg"; + _inventory.push_back(inventoryAdditionObject); emit buyResult(""); } @@ -69,6 +73,9 @@ void Ledger::balance(const QStringList& keys) { void Ledger::inventory(const QStringList& keys) { // FIXME: talk to server instead - qCInfo(commerce) << "Inventory:" << _inventory; - emit inventoryResult(_inventory, ""); + QJsonObject inventoryObject; + inventoryObject.insert("success", true); + inventoryObject.insert("assets", _inventory); + qCInfo(commerce) << "Inventory:" << inventoryObject; + emit inventoryResult(inventoryObject, ""); } \ No newline at end of file diff --git a/interface/src/commerce/Ledger.h b/interface/src/commerce/Ledger.h index 4cf6aec4ff..74ed8c1ab3 100644 --- a/interface/src/commerce/Ledger.h +++ b/interface/src/commerce/Ledger.h @@ -15,6 +15,8 @@ #define hifi_Ledger_h #include +#include +#include class Ledger : public QObject, public Dependency { Q_OBJECT @@ -30,12 +32,12 @@ signals: void buyResult(const QString& failureReason); void receiveAtResult(const QString& failureReason); void balanceResult(int balance, const QString& failureReason); - void inventoryResult(QStringList inventory, const QString& failureReason); + void inventoryResult(QJsonObject inventory, const QString& failureReason); private: // These in-memory caches is temporary, until we start sending things to the server. int _balance{ -1 }; - QStringList _inventory{}; + QJsonArray _inventory{}; int initializedBalance() { if (_balance < 0) _balance = 100; return _balance; } }; diff --git a/interface/src/commerce/QmlCommerce.h b/interface/src/commerce/QmlCommerce.h index 050371a801..0b1d232fd7 100644 --- a/interface/src/commerce/QmlCommerce.h +++ b/interface/src/commerce/QmlCommerce.h @@ -29,7 +29,7 @@ signals: // Balance and Inventory are NOT properties, because QML can't change them (without risk of failure), and // because we can't scalably know of out-of-band changes (e.g., another machine interacting with the block chain). void balanceResult(int balance, const QString& failureMessage); - void inventoryResult(QStringList inventory, const QString& failureMessage); + void inventoryResult(QJsonObject inventory, const QString& failureMessage); protected: Q_INVOKABLE void buy(const QString& assetId, int cost, const QString& buyerUsername = ""); From c1d771842d5b198e96b324508b761bc1fd1d71df Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 14 Aug 2017 13:37:50 -0700 Subject: [PATCH 44/54] Remove context overlay (if present) when removing entity --- interface/src/ui/overlays/ContextOverlayInterface.cpp | 8 ++++++++ interface/src/ui/overlays/ContextOverlayInterface.h | 1 + 2 files changed, 9 insertions(+) diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp index 03a75c71dd..46fb2df007 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.cpp +++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp @@ -55,6 +55,8 @@ ContextOverlayInterface::ContextOverlayInterface() { _contextOverlayJustClicked = false; } }); + auto entityScriptingInterface = DependencyManager::get().data(); + connect(entityScriptingInterface, &EntityScriptingInterface::deletingEntity, this, &ContextOverlayInterface::deletingEntity); } static const uint32_t LEFT_HAND_HW_ID = 1; @@ -278,3 +280,9 @@ void ContextOverlayInterface::disableEntityHighlight(const EntityItemID& entityI } }); } + +void ContextOverlayInterface::deletingEntity(const EntityItemID& entityID) { + if (_currentEntityWithContextOverlay == entityID) { + destroyContextOverlay(_currentEntityWithContextOverlay, PointerEvent()); + } +} diff --git a/interface/src/ui/overlays/ContextOverlayInterface.h b/interface/src/ui/overlays/ContextOverlayInterface.h index ba9cb68575..b386de08cc 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.h +++ b/interface/src/ui/overlays/ContextOverlayInterface.h @@ -80,6 +80,7 @@ private: void enableEntityHighlight(const EntityItemID& entityItemID); void disableEntityHighlight(const EntityItemID& entityItemID); + void deletingEntity(const EntityItemID& entityItemID); }; #endif // hifi_ContextOverlayInterface_h From e7a4bff705a8764ab72bbc4edb37a009a664ee4c Mon Sep 17 00:00:00 2001 From: Cain Kilgore Date: Mon, 14 Aug 2017 22:47:18 +0100 Subject: [PATCH 45/54] Made Changes per Review, added js --- .../resources/qml/hifi/SkyboxChanger.qml | 21 +--- .../skyboxChanger/skyboxchanger.js | 118 ++++++++++++++++++ 2 files changed, 123 insertions(+), 16 deletions(-) create mode 100644 unpublishedScripts/marketplace/skyboxChanger/skyboxchanger.js diff --git a/interface/resources/qml/hifi/SkyboxChanger.qml b/interface/resources/qml/hifi/SkyboxChanger.qml index 6291a1c103..a4798ba959 100644 --- a/interface/resources/qml/hifi/SkyboxChanger.qml +++ b/interface/resources/qml/hifi/SkyboxChanger.qml @@ -9,26 +9,11 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -import QtQuick 2.5 -import QtQuick.Controls 1.5 as QQControls import QtQuick.Layouts 1.3 -import QtQuick.Controls.Styles 1.4 - -import QtWebEngine 1.2 -import QtWebChannel 1.0 - -import "../styles-uit" -import "../controls-uit" as HifiControls -import "../windows" -import "../controls" Rectangle { id: root; - HifiConstants { id: hifi; } - - property string title: ""; - color: hifi.colors.baseGray; Item { @@ -62,7 +47,7 @@ Rectangle { size: 14; // Anchors anchors.fill: parent; - anchors.topMargin: 56; + anchors.top: titleBarText.bottom anchors.leftMargin: 16; anchors.rightMargin: 16; // Style @@ -72,6 +57,10 @@ Rectangle { verticalAlignment: Text.AlignVCenter; } } + + // This RowLayout could be a GridLayout instead for further expandability. + // As this SkyboxChanger task only required 6 images, implementing GridLayout wasn't necessary. + // In the future if this is to be expanded to add more Skyboxes, it might be worth changing this. RowLayout { id: row1 anchors.top: titleBarContainer.bottom diff --git a/unpublishedScripts/marketplace/skyboxChanger/skyboxchanger.js b/unpublishedScripts/marketplace/skyboxChanger/skyboxchanger.js new file mode 100644 index 0000000000..e7a135ec9e --- /dev/null +++ b/unpublishedScripts/marketplace/skyboxChanger/skyboxchanger.js @@ -0,0 +1,118 @@ +"use strict"; + +// +// skyboxchanger.js +// +// Created by Cain Kilgore on 9th August 2017 +// Copyright 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 +// + +(function() { + var TABLET_BUTTON_NAME = "SKYBOX"; + + var ICONS = { + icon: "http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/skyboxedit-i.svg", + activeIcon: "http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/skyboxedit-i.svg" + }; + + var onSkyboxChangerScreen = false; + + function onClicked() { + if (onSkyboxChangerScreen) { + tablet.gotoHomeScreen(); + } else { + tablet.loadQMLSource("../SkyboxChanger.qml"); + } + } + + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var button = tablet.addButton({ + icon: ICONS.icon, + activeIcon: ICONS.activeIcon, + text: TABLET_BUTTON_NAME, + sortOrder: 1 + }); + + var hasEventBridge = false; + + function wireEventBridge(on) { + if (!tablet) { + print("Warning in wireEventBridge(): 'tablet' undefined!"); + return; + } + if (on) { + if (!hasEventBridge) { + tablet.fromQml.connect(fromQml); + hasEventBridge = true; + } + } else { + if (hasEventBridge) { + tablet.fromQml.disconnect(fromQml); + hasEventBridge = false; + } + } + } + + function onScreenChanged(type, url) { + if (url === "../SkyboxChanger.qml") { + onSkyboxChangerScreen = true; + } else { + onSkyboxChangerScreen = false; + } + + button.editProperties({isActive: onSkyboxChangerScreen}); + wireEventBridge(onSkyboxChangerScreen); + } + + function fromQml(message) { + switch (message.method) { + case 'changeSkybox': // changeSkybox Code + var standingZone; + if (!Entities.canRez()) { + Window.alert("You need to have rez permissions to change the Skybox."); + break; + } + + var nearbyEntities = Entities.findEntities(MyAvatar.position, 5); + for (var i = 0; i < nearbyEntities.length; i++) { + if (Entities.getEntityProperties(nearbyEntities[i]).type === "Zone") { + standingZone = nearbyEntities[i]; + } + } + + if (Entities.getEntityProperties(standingZone).locked) { + Window.alert("This zone is currently locked; the Skybox can't be changed."); + break; + } + + var newSkybox = { + skybox: { + url: message.url + }, + keyLight: { + ambientURL: message.url + } + }; + + Entities.editEntity(standingZone, newSkybox); + break; + default: + print('Unrecognized message from QML: ' + JSON.stringify(message)); + } + } + + button.clicked.connect(onClicked); + tablet.screenChanged.connect(onScreenChanged); + + Script.scriptEnding.connect(function () { + if (onSkyboxChangerScreen) { + tablet.gotoHomeScreen(); + } + button.clicked.disconnect(onClicked); + tablet.screenChanged.disconnect(onScreenChanged); + tablet.removeButton(button); + }); +}()); \ No newline at end of file From 816343028203ef50eeae2bb30d26cffdd09af776 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 14 Aug 2017 15:03:14 -0700 Subject: [PATCH 46/54] fix depth buffer issue that was messing with drawInFront, plus some small fixes to line3ds --- interface/src/ui/overlays/Line3DOverlay.cpp | 12 ++++++------ libraries/render-utils/src/GeometryCache.cpp | 6 +++++- libraries/render-utils/src/RenderDeferredTask.cpp | 2 +- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/interface/src/ui/overlays/Line3DOverlay.cpp b/interface/src/ui/overlays/Line3DOverlay.cpp index 900c79fc3f..d8fe0e6bb8 100644 --- a/interface/src/ui/overlays/Line3DOverlay.cpp +++ b/interface/src/ui/overlays/Line3DOverlay.cpp @@ -32,6 +32,8 @@ Line3DOverlay::Line3DOverlay(const Line3DOverlay* line3DOverlay) : _length = line3DOverlay->getLength(); _endParentID = line3DOverlay->getEndParentID(); _endParentJointIndex = line3DOverlay->getEndJointIndex(); + _glow = line3DOverlay->getGlow(); + _glowWidth = line3DOverlay->getGlowWidth(); } Line3DOverlay::~Line3DOverlay() { @@ -138,11 +140,9 @@ void Line3DOverlay::render(RenderArgs* args) { // TODO: add support for color to renderDashedLine() geometryCache->bindSimpleProgram(*batch, false, false, false, true, true); geometryCache->renderDashedLine(*batch, start, end, colorv4, _geometryCacheID); - } else if (_glow > 0.0f) { - geometryCache->renderGlowLine(*batch, start, end, colorv4, _glow, _glowWidth, _geometryCacheID); } else { - geometryCache->bindSimpleProgram(*batch, false, false, false, true, true); - geometryCache->renderLine(*batch, start, end, colorv4, _geometryCacheID); + // renderGlowLine handles both glow = 0 and glow > 0 cases + geometryCache->renderGlowLine(*batch, start, end, colorv4, _glow, _glowWidth, _geometryCacheID); } } } @@ -228,9 +228,9 @@ void Line3DOverlay::setProperties(const QVariantMap& originalProperties) { } } - auto glowWidth = properties["glow"]; + auto glowWidth = properties["glowWidth"]; if (glowWidth.isValid()) { - setGlow(glowWidth.toFloat()); + setGlowWidth(glowWidth.toFloat()); } } diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 5f2acff16f..d7cd860d50 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -1640,7 +1640,11 @@ void GeometryCache::renderGlowLine(gpu::Batch& batch, const glm::vec3& p1, const #endif if (glowIntensity <= 0) { - bindSimpleProgram(batch, false, false, false, true, false); + if (color.a >= 1.0) { + bindSimpleProgram(batch, false, false, false, true, true); + } else { + bindSimpleProgram(batch, false, true, false, true, true); + } renderLine(batch, p1, p2, color, id); return; } diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 20c999019b..c1b2d7fd7b 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -357,7 +357,7 @@ void DrawOverlay3D::run(const RenderContextPointer& renderContext, const Inputs& if (_opaquePass) { gpu::doInBatch(args->_context, [&](gpu::Batch& batch){ batch.enableStereo(false); - batch.clearFramebuffer(gpu::Framebuffer::BUFFER_DEPTH, glm::vec4(), 1.f, 0, true); + batch.clearFramebuffer(gpu::Framebuffer::BUFFER_DEPTH, glm::vec4(), 1.f, 0, false); }); } From 99617600c47c7e8eb613ae1f28bc73cf1a1b9f63 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Mon, 14 Aug 2017 15:58:28 -0700 Subject: [PATCH 47/54] fix selection issue for TreeView.qml --- interface/resources/qml/controls-uit/Tree.qml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/interface/resources/qml/controls-uit/Tree.qml b/interface/resources/qml/controls-uit/Tree.qml index 8bce092947..6c9533a40c 100644 --- a/interface/resources/qml/controls-uit/Tree.qml +++ b/interface/resources/qml/controls-uit/Tree.qml @@ -27,6 +27,7 @@ TreeView { model: treeModel selection: ItemSelectionModel { + id: selectionModel model: treeModel } @@ -215,6 +216,10 @@ TreeView { onDoubleClicked: isExpanded(index) ? collapse(index) : expand(index) + onClicked: { + selectionModel.setCurrentIndex(index, ItemSelectionModel.ClearAndSelect); + } + onActivated: { var path = scriptsModel.data(index, 0x100) if (path) { From 459f2c5cdcaf9240573df5b0732f3e62ae6451c4 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Mon, 14 Aug 2017 16:03:12 -0700 Subject: [PATCH 48/54] fixed tab issue --- interface/resources/qml/controls-uit/Tree.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/controls-uit/Tree.qml b/interface/resources/qml/controls-uit/Tree.qml index 6c9533a40c..53f66fa67c 100644 --- a/interface/resources/qml/controls-uit/Tree.qml +++ b/interface/resources/qml/controls-uit/Tree.qml @@ -27,7 +27,7 @@ TreeView { model: treeModel selection: ItemSelectionModel { - id: selectionModel + id: selectionModel model: treeModel } @@ -217,7 +217,7 @@ TreeView { onDoubleClicked: isExpanded(index) ? collapse(index) : expand(index) onClicked: { - selectionModel.setCurrentIndex(index, ItemSelectionModel.ClearAndSelect); + selectionModel.setCurrentIndex(index, ItemSelectionModel.ClearAndSelect); } onActivated: { From 194b7d6655339ef02f6122fd769df78d9a9ae22e Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 14 Aug 2017 16:08:07 -0700 Subject: [PATCH 49/54] warning --- libraries/render-utils/src/GeometryCache.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index d7cd860d50..1fb78d8cf3 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -1639,8 +1639,8 @@ void GeometryCache::renderGlowLine(gpu::Batch& batch, const glm::vec3& p1, const glowIntensity = 0.0f; #endif - if (glowIntensity <= 0) { - if (color.a >= 1.0) { + if (glowIntensity <= 0.0f) { + if (color.a >= 1.0f) { bindSimpleProgram(batch, false, false, false, true, true); } else { bindSimpleProgram(batch, false, true, false, true, true); From 04006a9f76047f6d65d1d34b181732148aca73ed Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 15 Aug 2017 11:19:41 -0700 Subject: [PATCH 50/54] code review feedback --- interface/src/avatar/MyAvatar.cpp | 3 ++- libraries/animation/src/Rig.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 2109aa7dfa..77fa0cfda3 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1811,7 +1811,7 @@ void MyAvatar::postUpdate(float deltaTime) { updateHoldActions(_prePhysicsRoomPose, postUpdateRoomPose); if (_enableDebugDrawDetailedCollision) { - AnimPose rigToWorldPose(glm::vec3(1.0f), Quaternions::Y_180 * getRotation(), getPosition()); + AnimPose rigToWorldPose(glm::vec3(1.0f), getRotation() * Quaternions::Y_180, getPosition()); const int NUM_DEBUG_COLORS = 7; const glm::vec4 DEBUG_COLORS[NUM_DEBUG_COLORS] = { glm::vec4(1.0f, 1.0f, 1.0f, 1.0f), @@ -1821,6 +1821,7 @@ void MyAvatar::postUpdate(float deltaTime) { glm::vec4(1.0f, 1.0f, 0.0f, 1.0f), glm::vec4(0.25f, 1.0f, 1.0f, 1.0f), glm::vec4(1.0f, 0.25f, 1.0f, 1.0f), + glm::vec4(1.0f, 0.65f, 0.0f, 1.0f) // Orange you glad I added this color? }; if (_skeletonModel && _skeletonModel->isLoaded()) { diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index e01624655b..3a31ccd25f 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1118,7 +1118,7 @@ const glm::vec3 DOP14_NORMALS[DOP14_COUNT] = { -glm::vec3(INV_SQRT_3, -INV_SQRT_3, -INV_SQRT_3) }; -// returns true if the given point lies in side of the k-dop, specified by shapeInfo & shapePose. +// returns true if the given point lies inside of the k-dop, specified by shapeInfo & shapePose. // if the given point does lie within the k-dop, it also returns the amount of displacement necessary to push that point outward // such that it lies on the surface of the kdop. static bool findPointKDopDisplacement(const glm::vec3& point, const AnimPose& shapePose, const FBXJointShapeInfo& shapeInfo, glm::vec3& displacementOut) { From 6e0ddadb29e6356f1e42d6872a774b66149609cf Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 15 Aug 2017 11:45:22 -0700 Subject: [PATCH 51/54] Fix for array size. --- interface/src/avatar/MyAvatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 77fa0cfda3..e2613a207a 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1812,7 +1812,7 @@ void MyAvatar::postUpdate(float deltaTime) { if (_enableDebugDrawDetailedCollision) { AnimPose rigToWorldPose(glm::vec3(1.0f), getRotation() * Quaternions::Y_180, getPosition()); - const int NUM_DEBUG_COLORS = 7; + const int NUM_DEBUG_COLORS = 8; const glm::vec4 DEBUG_COLORS[NUM_DEBUG_COLORS] = { glm::vec4(1.0f, 1.0f, 1.0f, 1.0f), glm::vec4(1.0f, 0.0f, 0.0f, 1.0f), From c0fa446b75de60f5d51d6ab3a07e6bd692495f6f Mon Sep 17 00:00:00 2001 From: Liv Date: Tue, 15 Aug 2017 13:49:13 -0700 Subject: [PATCH 52/54] Remove domain management scripting interface --- .../DomainManagementScriptingInterface.cpp | 29 -------------- .../DomainManagementScriptingInterface.h | 39 ------------------- 2 files changed, 68 deletions(-) delete mode 100644 interface/src/scripting/DomainManagementScriptingInterface.cpp delete mode 100644 interface/src/scripting/DomainManagementScriptingInterface.h diff --git a/interface/src/scripting/DomainManagementScriptingInterface.cpp b/interface/src/scripting/DomainManagementScriptingInterface.cpp deleted file mode 100644 index 593fedad3c..0000000000 --- a/interface/src/scripting/DomainManagementScriptingInterface.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// -// DomainManagementScriptingInterface.cpp -// interface/src/scripting -// -// Created by Liv Erickson on 7/21/17. -// Copyright 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 "DomainManagementScriptingInterface.h" -#include "Application.h" -#include "OffscreenUi.h" - -DomainManagementScriptingInterface::DomainManagementScriptingInterface() -{ - auto nodeList = DependencyManager::get(); - connect(nodeList.data(), &NodeList::canReplaceContentChanged, this, &DomainManagementScriptingInterface::canReplaceDomainContentChanged); -} - -DomainManagementScriptingInterface::~DomainManagementScriptingInterface() { - auto nodeList = DependencyManager::get(); - disconnect(nodeList.data(), &NodeList::canReplaceContentChanged, this, &DomainManagementScriptingInterface::canReplaceDomainContentChanged); -} - -bool DomainManagementScriptingInterface::canReplaceDomainContent() { - auto nodeList = DependencyManager::get(); - return nodeList->getThisNodeCanReplaceContent(); -} diff --git a/interface/src/scripting/DomainManagementScriptingInterface.h b/interface/src/scripting/DomainManagementScriptingInterface.h deleted file mode 100644 index 85955254c7..0000000000 --- a/interface/src/scripting/DomainManagementScriptingInterface.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// DomainManagementScriptingInterface.h -// interface/src/scripting -// -// Created by Liv Erickson on 7/21/17. -// Copyright 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_DomainManagementScriptingInterface_h -#define hifi_DomainManagementScriptingInterface_h - -#include -#include -#include -#include -#include -#include -#include - -#include "BaseScriptEngine.h" - - -class DomainManagementScriptingInterface : public QObject, public Dependency { -Q_OBJECT -public: - DomainManagementScriptingInterface(); - ~DomainManagementScriptingInterface(); - - -public slots: - Q_INVOKABLE bool canReplaceDomainContent(); - -signals: - void canReplaceDomainContentChanged(bool canReplaceDomainContent); -}; - -#endif //hifi_DomainManagementScriptingInterface_h \ No newline at end of file From 49eab847fd98e8ee83672340a5c617364500f885 Mon Sep 17 00:00:00 2001 From: Liv Date: Tue, 15 Aug 2017 13:58:02 -0700 Subject: [PATCH 53/54] Refactor handleOctreeFileReplacement, style changes, align with handler for other file types --- assignment-client/src/octree/OctreeServer.cpp | 98 +++++++------------ assignment-client/src/octree/OctreeServer.h | 2 + interface/src/Application.cpp | 17 ++-- 3 files changed, 42 insertions(+), 75 deletions(-) diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index d6a0cc7b92..ff155b89c0 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -935,39 +935,7 @@ void OctreeServer::handleOctreeFileReplacement(QSharedPointer m // so here we just store a special file at our persist path // and then force a stop of the server so that it can pick it up when it relaunches if (!_persistAbsoluteFilePath.isEmpty()) { - - // before we restart the server and make it try and load this data, let's make sure it is valid - auto compressedOctree = message->getMessage(); - QByteArray jsonOctree; - - // assume we have GZipped content - bool wasCompressed = gunzip(compressedOctree, jsonOctree); - if (!wasCompressed) { - // the source was not compressed, assume we were sent regular JSON data - jsonOctree = compressedOctree; - } - - // check the JSON data to verify it is an object - if (QJsonDocument::fromJson(jsonOctree).isObject()) { - if (!wasCompressed) { - // source was not compressed, we compress it before we write it locally - gzip(jsonOctree, compressedOctree); - } - - // write the compressed octree data to a special file - auto replacementFilePath = _persistAbsoluteFilePath.append(OctreePersistThread::REPLACEMENT_FILE_EXTENSION); - QFile replacementFile(replacementFilePath); - if (replacementFile.open(QIODevice::WriteOnly) && replacementFile.write(compressedOctree) != -1) { - // we've now written our replacement file, time to take the server down so it can - // process it when it comes back up - qInfo() << "Wrote octree replacement file to" << replacementFilePath << "- stopping server"; - setFinished(true); - } else { - qWarning() << "Could not write replacement octree data to file - refusing to process"; - } - } else { - qDebug() << "Received replacement octree file that is invalid - refusing to process"; - } + OctreeServer::replaceContentFromMessageData(message->getMessage()); } else { qDebug() << "Cannot perform octree file replacement since current persist file path is not yet known"; } @@ -995,37 +963,7 @@ void OctreeServer::handleOctreeFileReplacementFromURL(QSharedPointererror(); if (networkError == QNetworkReply::NoError) { QByteArray contents = reply->readAll(); - - // Like above, assume we have compressed data - auto compressedOctree = contents; - QByteArray jsonOctree; - - bool wasCompressed = gunzip(compressedOctree, jsonOctree); - if (!wasCompressed) { - // the source was not compressed, assume we were sent regular JSON data - jsonOctree = compressedOctree; - } - // check the JSON data to verify it is an object - if (QJsonDocument::fromJson(jsonOctree).isObject()) { - if (!wasCompressed) { - // source was not compressed, we compress it before we write it locally - gzip(jsonOctree, compressedOctree); - } - - // write the compressed octree data to a special file - auto replacementFilePath = _persistAbsoluteFilePath.append(OctreePersistThread::REPLACEMENT_FILE_EXTENSION); - QFile replacementFile(replacementFilePath); - if (replacementFile.open(QIODevice::WriteOnly) && replacementFile.write(compressedOctree) != -1) { - // we've now written our replacement file, time to take the server down so it can - // process it when it comes back up - qInfo() << "Wrote octree replacement file to" << replacementFilePath << "- stopping server"; - setFinished(true); - } else { - qWarning() << "Could not write replacement octree data to file - refusing to process"; - } - } else { - qDebug() << "Received replacement octree file that is invalid - refusing to process"; - } + OctreeServer::replaceContentFromMessageData(contents); } else { qDebug() << "Error downloading JSON from specified file"; } @@ -1037,6 +975,38 @@ void OctreeServer::handleOctreeFileReplacementFromURL(QSharedPointer(); DependencyManager::set(); DependencyManager::set(); - DependencyManager::set(); DependencyManager::set(true); DependencyManager::set(); DependencyManager::set(); @@ -2154,7 +2152,6 @@ void Application::initializeUi() { surfaceContext->setContextProperty("Render", _renderEngine->getConfiguration().get()); surfaceContext->setContextProperty("Reticle", getApplicationCompositor().getReticleInterface()); surfaceContext->setContextProperty("Snapshot", DependencyManager::get().data()); - surfaceContext->setContextProperty("DomainManagement", DependencyManager::get().data()); surfaceContext->setContextProperty("ApplicationCompositor", &getApplicationCompositor()); @@ -5834,7 +5831,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("OffscreenFlags", DependencyManager::get()->getFlags()); scriptEngine->registerGlobalObject("Desktop", DependencyManager::get().data()); - scriptEngine->registerGlobalObject("DomainManagement", DependencyManager::get().data()); qScriptRegisterMetaType(scriptEngine, wrapperToScriptValue, wrapperFromScriptValue); qScriptRegisterMetaType(scriptEngine, wrapperToScriptValue, wrapperFromScriptValue); @@ -6127,7 +6123,7 @@ bool Application::askToWearAvatarAttachmentUrl(const QString& url) { bool Application::askToReplaceDomainContent(const QString& url) { QString methodDetails; if (DependencyManager::get()->getThisNodeCanReplaceContent()) { - QUrl originURL{ url }; + QUrl originURL { url }; if (originURL.host().endsWith(MARKETPLACE_CDN_HOSTNAME)) { // Create a confirmation dialog when this call is made const int MAX_CHARACTERS_PER_LINE = 90; @@ -6143,15 +6139,14 @@ bool Application::askToReplaceDomainContent(const QString& url) { if (agreeToReplaceContent) { // Given confirmation, send request to domain server to replace content qCDebug(interfaceapp) << "Attempting to replace domain content: " << url; - QByteArray _url(url.toUtf8()); + QByteArray urlData(url.toUtf8()); auto limitedNodeList = DependencyManager::get(); limitedNodeList->eachMatchingNode([](const SharedNodePointer& node) { return node->getType() == NodeType::EntityServer && node->getActiveSocket(); - }, [&_url, limitedNodeList](const SharedNodePointer& octreeNode) { - auto octreeFilePacket = NLPacket::create(PacketType::OctreeFileReplacementFromUrl, _url.size(), true); - octreeFilePacket->write(_url); + }, [&urlData, limitedNodeList](const SharedNodePointer& octreeNode) { + auto octreeFilePacket = NLPacket::create(PacketType::OctreeFileReplacementFromUrl, urlData.size(), true); + octreeFilePacket->write(urlData); limitedNodeList->sendPacket(std::move(octreeFilePacket), *octreeNode); - return true; }); DependencyManager::get()->handleLookupString(DOMAIN_SPAWNING_POINT); methodDetails = "SuccessfulRequestToReplaceContent"; @@ -6171,7 +6166,7 @@ bool Application::askToReplaceDomainContent(const QString& url) { { "content_set_url", url } }; UserActivityLogger::getInstance().logAction("replace_domain_content", messageProperties); - return false; + return true; } void Application::displayAvatarAttachmentWarning(const QString& message) const { From 1ae4a5c01901120e6b653a358c2954ffe688f0f3 Mon Sep 17 00:00:00 2001 From: Liv Date: Tue, 15 Aug 2017 15:30:43 -0700 Subject: [PATCH 54/54] remove class from function call --- assignment-client/src/octree/OctreeServer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index ff155b89c0..db97da751f 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -935,7 +935,7 @@ void OctreeServer::handleOctreeFileReplacement(QSharedPointer m // so here we just store a special file at our persist path // and then force a stop of the server so that it can pick it up when it relaunches if (!_persistAbsoluteFilePath.isEmpty()) { - OctreeServer::replaceContentFromMessageData(message->getMessage()); + replaceContentFromMessageData(message->getMessage()); } else { qDebug() << "Cannot perform octree file replacement since current persist file path is not yet known"; } @@ -963,7 +963,7 @@ void OctreeServer::handleOctreeFileReplacementFromURL(QSharedPointererror(); if (networkError == QNetworkReply::NoError) { QByteArray contents = reply->readAll(); - OctreeServer::replaceContentFromMessageData(contents); + replaceContentFromMessageData(contents); } else { qDebug() << "Error downloading JSON from specified file"; }