From 3712e1453073d040ae127100cde04de17dd4dc4d Mon Sep 17 00:00:00 2001 From: Liv Date: Tue, 18 Jul 2017 10:02:46 -0700 Subject: [PATCH 01/56] 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/56] 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/56] 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/56] 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/56] 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/56] 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/56] 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/56] 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/56] 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/56] 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/56] 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/56] 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/56] 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/56] 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 d2abc42e8f93a36f13e0092496966ffeeb4857c8 Mon Sep 17 00:00:00 2001 From: Liv Date: Mon, 7 Aug 2017 12:43:54 -0700 Subject: [PATCH 15/56] 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 16/56] 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 17/56] 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 18/56] 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 48e327815dd7ba973cd6f9bf3e62c7746076b490 Mon Sep 17 00:00:00 2001 From: LaShonda Hopper <1p-cusack@1stplayable.com> Date: Tue, 1 Aug 2017 16:26:45 -0400 Subject: [PATCH 19/56] [Case 6491] Resolves arg order to centerToZero and centerToIntersection vectors. Changes Committed: modified: scripts/system/libraries/entitySelectionTool.js --- .../system/libraries/entitySelectionTool.js | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index 77b62913bf..30d54e3530 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -3549,6 +3549,8 @@ SelectionDisplay = (function() { }); } + //----------------------------------------- + // YAW GRABBER TOOL DEFINITION var initialPosition = SelectionManager.worldPosition; addGrabberTool(yawHandle, { mode: "ROTATE_YAW", @@ -3625,10 +3627,10 @@ SelectionDisplay = (function() { if (result.intersects) { var center = yawCenter; var zero = yawZero; - // TODO: these vectors are backwards to their names, doesn't matter for this use case (inverted vectors still give same angle) - var centerToZero = Vec3.subtract(center, zero); - var centerToIntersect = Vec3.subtract(center, result.intersection); - // TODO: orientedAngle wants normalized centerToZero and centerToIntersect + var centerToZero = Vec3.subtract(zero, center); + var centerToIntersect = Vec3.subtract(result.intersection, center); + // Note: orientedAngle which wants normalized centerToZero and centerToIntersect + // handles that internally, so it's to pass unnormalized vectors here. var angleFromZero = Vec3.orientedAngle(centerToZero, centerToIntersect, rotationNormal); var distanceFromCenter = Vec3.distance(center, result.intersection); var snapToInner = distanceFromCenter < innerRadius; @@ -3717,6 +3719,8 @@ SelectionDisplay = (function() { } }); + //----------------------------------------- + // PITCH GRABBER TOOL DEFINITION addGrabberTool(pitchHandle, { mode: "ROTATE_PITCH", onBegin: function(event) { @@ -3792,8 +3796,10 @@ SelectionDisplay = (function() { var properties = Entities.getEntityProperties(selectionManager.selections[0]); var center = pitchCenter; var zero = pitchZero; - var centerToZero = Vec3.subtract(center, zero); - var centerToIntersect = Vec3.subtract(center, result.intersection); + var centerToZero = Vec3.subtract(zero, center); + var centerToIntersect = Vec3.subtract(result.intersection, center); + // Note: orientedAngle which wants normalized centerToZero & centerToIntersect, handles + // this internally, so it's fine to pass non-normalized versions here. var angleFromZero = Vec3.orientedAngle(centerToZero, centerToIntersect, rotationNormal); var distanceFromCenter = Vec3.distance(center, result.intersection); @@ -3874,6 +3880,8 @@ SelectionDisplay = (function() { } }); + //----------------------------------------- + // ROLL GRABBER TOOL DEFINITION addGrabberTool(rollHandle, { mode: "ROTATE_ROLL", onBegin: function(event) { @@ -3949,8 +3957,10 @@ SelectionDisplay = (function() { var properties = Entities.getEntityProperties(selectionManager.selections[0]); var center = rollCenter; var zero = rollZero; - var centerToZero = Vec3.subtract(center, zero); - var centerToIntersect = Vec3.subtract(center, result.intersection); + var centerToZero = Vec3.subtract(zero, center); + var centerToIntersect = Vec3.subtract(result.intersection, center); + // Note: orientedAngle which wants normalized centerToZero & centerToIntersect, handles + // this internally, so it's fine to pass non-normalized versions here. var angleFromZero = Vec3.orientedAngle(centerToZero, centerToIntersect, rotationNormal); var distanceFromCenter = Vec3.distance(center, result.intersection); From bd1619b1b2a49add36a710492b684c3508dd97d3 Mon Sep 17 00:00:00 2001 From: Liv Date: Wed, 9 Aug 2017 09:14:46 -0700 Subject: [PATCH 20/56] 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/56] 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/56] 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 ae98974d792345e91cbf7c3515499aae4ab7be4a Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 10 Aug 2017 15:52:51 -0700 Subject: [PATCH 23/56] 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 24/56] 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 25/56] 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 26/56] 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 f784bc42def386b6b5c5c4acda81c1548c81eff7 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Fri, 11 Aug 2017 16:54:04 -0700 Subject: [PATCH 27/56] Initial cut using RSA keys for now --- interface/CMakeLists.txt | 6 + interface/src/commerce/Ledger.cpp | 8 +- interface/src/commerce/Wallet.cpp | 253 ++++++++++++++++++++++++++++-- interface/src/commerce/Wallet.h | 3 +- 4 files changed, 256 insertions(+), 14 deletions(-) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 81c8a44baf..4ed95b59f7 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -183,6 +183,12 @@ if (WIN32) add_dependency_external_projects(steamworks) endif() +# include OPENSSL +include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") + +# append OpenSSL to our list of libraries to link +target_link_libraries(${TARGET_NAME} ${OPENSSL_LIBRARIES}) + # disable /OPT:REF and /OPT:ICF for the Debug builds # This will prevent the following linker warnings # LINK : warning LNK4075: ignoring '/INCREMENTAL' due to '/OPT:ICF' specification diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index 0d9d780743..5973701633 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -24,12 +24,12 @@ bool Ledger::buy(const QString& hfc_key, int cost, const QString& asset_id, cons transaction["inventory_key"] = inventory_key; transaction["inventory_buyer_username"] = buyerUsername; QJsonDocument transactionDoc{ transaction }; - QString transactionString = transactionDoc.toJson(QJsonDocument::Compact); - + auto transactionString = transactionDoc.toJson(QJsonDocument::Compact); + auto wallet = DependencyManager::get(); QString signature = wallet->signWithKey(transactionString, hfc_key); QJsonObject request; - request["transaction"] = transactionString; + request["transaction"] = QString(transactionString); request["signature"] = signature; qCInfo(commerce) << "Transaction:" << QJsonDocument(request).toJson(QJsonDocument::Compact); @@ -45,4 +45,4 @@ bool Ledger::receiveAt(const QString& hfc_key) { auto username = accountManager->getAccountInfo().getUsername(); qCInfo(commerce) << "Setting default receiving key for" << username; return true; // FIXME send to server. -} \ No newline at end of file +} diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index d2a6ae4809..6f0329b8ba 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -9,25 +9,230 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include #include "CommerceLogging.h" #include "Ledger.h" #include "Wallet.h" +#include + +#include + +#include +#include +#include +#include +#include +#include + +static const char* PUBLIC_KEY_FILE = "hifikey.pub"; +static const char* PRIVATE_KEY_FILE = "hifikey"; + +void initialize() { + static bool initialized = false; + if (!initialized) { + SSL_load_error_strings(); + SSL_library_init(); + OpenSSL_add_all_algorithms(); + initialized = true; + } +} + +QString publicKeyFilePath() { + return PathUtils::getAppDataFilePath(PUBLIC_KEY_FILE); +} + +QString privateKeyFilePath() { + return PathUtils::getAppDataFilePath(PRIVATE_KEY_FILE); +} +// for now the callback function just returns the same string. Later we can hook +// this to the gui (some thought required) + +int passwordCallback(char* password, int maxPasswordSize, int rwFlag, void* u) { + // just return a hardcoded pwd for now + static const char* pwd = "pwd"; + strcpy(password, pwd); + return strlen(pwd); +} + +// BEGIN copied code - this will be removed/changed at some point soon +// copied (without emits for various signals) from libraries/networking/src/RSAKeypairGenerator.cpp. +// We will have a different implementation in practice, but this gives us a start for now +QPair generateRSAKeypair() { + + RSA* keyPair = RSA_new(); + BIGNUM* exponent = BN_new(); + QPair retval; + + const unsigned long RSA_KEY_EXPONENT = 65537; + BN_set_word(exponent, RSA_KEY_EXPONENT); + + // seed the random number generator before we call RSA_generate_key_ex + srand(time(NULL)); + + const int RSA_KEY_BITS = 2048; + + if (!RSA_generate_key_ex(keyPair, RSA_KEY_BITS, exponent, NULL)) { + qCDebug(commerce) << "Error generating 2048-bit RSA Keypair -" << ERR_get_error(); + + // we're going to bust out of here but first we cleanup the BIGNUM + BN_free(exponent); + return retval; + } + + // we don't need the BIGNUM anymore so clean that up + BN_free(exponent); + + // grab the public key and private key from the file + unsigned char* publicKeyDER = NULL; + int publicKeyLength = i2d_RSAPublicKey(keyPair, &publicKeyDER); + + unsigned char* privateKeyDER = NULL; + int privateKeyLength = i2d_RSAPrivateKey(keyPair, &privateKeyDER); + + if (publicKeyLength <= 0 || privateKeyLength <= 0) { + qCDebug(commerce) << "Error getting DER public or private key from RSA struct -" << ERR_get_error(); + + + // cleanup the RSA struct + RSA_free(keyPair); + + // cleanup the public and private key DER data, if required + if (publicKeyLength > 0) { + OPENSSL_free(publicKeyDER); + } + + if (privateKeyLength > 0) { + OPENSSL_free(privateKeyDER); + } + + return retval; + } + + + + // now lets persist them to files + // TODO: figure out a scheme for multiple keys, etc... + FILE* fp; + if (fp = fopen(publicKeyFilePath().toStdString().c_str(), "wt")) { + if (!PEM_write_RSAPublicKey(fp, keyPair)) { + fclose(fp); + qCDebug(commerce) << "failed to write public key"; + return retval; + } + fclose(fp); + } + + if (fp = fopen(privateKeyFilePath().toStdString().c_str(), "wt")) { + char pwd[] = "pwd"; + if (!PEM_write_RSAPrivateKey(fp, keyPair, EVP_des_ede3_cbc(), NULL, 0, passwordCallback, NULL)) { + fclose(fp); + qCDebug(commerce) << "failed to write private key"; + return retval; + } + fclose(fp); + } + + RSA_free(keyPair); + + // prepare the return values + retval.first = new QByteArray(reinterpret_cast(publicKeyDER), publicKeyLength ), + retval.second = new QByteArray(reinterpret_cast(privateKeyDER), privateKeyLength ); + + // cleanup the publicKeyDER and publicKeyDER data + OPENSSL_free(publicKeyDER); + OPENSSL_free(privateKeyDER); + return retval; +} +// END copied code (which will soon change) + +// the public key can just go into a byte array +QByteArray readPublicKey(const char* filename) { + FILE* fp; + RSA* key = NULL; + if ( fp = fopen(filename, "r")) { + // file opened successfully + qCDebug(commerce) << "opened key file" << filename; + if (key = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL)) { + // file read successfully + unsigned char* publicKeyDER = NULL; + int publicKeyLength = i2d_RSAPublicKey(key, &publicKeyDER); + // TODO: check for 0 length? + + // cleanup + RSA_free(key); + fclose(fp); + + qCDebug(commerce) << "parsed public key file successfully"; + + QByteArray retval((char*)publicKeyDER, publicKeyLength); + OPENSSL_free(publicKeyDER); + return retval; + } else { + qCDebug(commerce) << "couldn't parse" << filename; + } + fclose(fp); + } else { + qCDebug(commerce) << "couldn't open" << filename; + } + return QByteArray(); +} + +// the private key should be read/copied into heap memory. For now, we need the RSA struct +// so I'll return that. Note we need to RSA_free(key) later!!! +RSA* readPrivateKey(const char* filename) { + FILE* fp; + RSA* key = NULL; + if ( fp = fopen(filename, "r")) { + // file opened successfully + qCDebug(commerce) << "opened key file" << filename; + if (key = PEM_read_RSAPrivateKey(fp, &key, passwordCallback, NULL)) { + // cleanup + fclose(fp); + + qCDebug(commerce) << "parsed private key file successfully"; + return key; + + } else { + qCDebug(commerce) << "couldn't parse" << filename; + } + fclose(fp); + } else { + qCDebug(commerce) << "couldn't open" << filename; + } + return false; +} + bool Wallet::createIfNeeded() { - // FIXME: persist in file between sessions. if (_publicKeys.count() > 0) return false; + + // FIXME: initialize OpenSSL elsewhere soon + initialize(); + + // try to read existing keys if they exist... + auto publicKey = readPublicKey(publicKeyFilePath().toStdString().c_str()); + if (publicKey.size() > 0) { + if (auto key = readPrivateKey(privateKeyFilePath().toStdString().c_str()) ) { + qCDebug(commerce) << "read private key"; + RSA_free(key); + // K -- add the public key since we have a legit private key associated with it + _publicKeys.push_back(publicKey.toBase64()); + return false; + } + } qCInfo(commerce) << "Creating wallet."; return generateKeyPair(); } bool Wallet::generateKeyPair() { - // FIXME: need private key, too, and persist in file. qCInfo(commerce) << "Generating keypair."; - QString key = QUuid::createUuid().toString(); - _publicKeys.push_back(key); + auto keyPair = generateRSAKeypair(); + + // TODO: do we need to pass params in here to make sure this is url-safe base64? + _publicKeys.push_back(keyPair.first->toBase64()); + qCDebug(commerce) << "public key:" << keyPair.first->toBase64(); + auto ledger = DependencyManager::get(); - return ledger->receiveAt(key); + return ledger->receiveAt(_publicKeys.last()); } QStringList Wallet::listPublicKeys() { qCInfo(commerce) << "Enumerating public keys."; @@ -35,7 +240,37 @@ QStringList Wallet::listPublicKeys() { return _publicKeys; } -QString Wallet::signWithKey(const QString& text, const QString& key) { +// for now a copy of how we sign in libraries/networking/src/DataServerAccountInfo - +// we sha256 the text, read the private key from disk (for now!), and return the signed +// sha256. Note later with multiple keys, we may need the key parameter (or something +// similar) so I left it alone for now. Also this will probably change when we move +// away from RSA keys anyways. Note that since this returns a QString, we better avoid +// the horror of code pages and so on (changing the bytes) by just returning a base64 +// encoded string representing the signature (suitable for http, etc...) +QString Wallet::signWithKey(const QByteArray& text, const QString& key) { qCInfo(commerce) << "Signing text."; - return "fixme signed"; -} \ No newline at end of file + RSA* rsaPrivateKey = NULL; + if (rsaPrivateKey = readPrivateKey(privateKeyFilePath().toStdString().c_str())) { + QByteArray signature(RSA_size(rsaPrivateKey), 0); + unsigned int signatureBytes = 0; + + QByteArray hashedPlaintext = QCryptographicHash::hash(text, QCryptographicHash::Sha256); + + int encryptReturn = RSA_sign(NID_sha256, + reinterpret_cast(hashedPlaintext.constData()), + hashedPlaintext.size(), + reinterpret_cast(signature.data()), + &signatureBytes, + rsaPrivateKey); + + // free the private key RSA struct now that we are done with it + RSA_free(rsaPrivateKey); + + if (encryptReturn != -1) { + // TODO: do we need to pass options in here to make sure it is url-safe? + return signature.toBase64(); + } + } + return QString(); +} + diff --git a/interface/src/commerce/Wallet.h b/interface/src/commerce/Wallet.h index 7cfb14c30d..a994f3e5b1 100644 --- a/interface/src/commerce/Wallet.h +++ b/interface/src/commerce/Wallet.h @@ -24,10 +24,11 @@ public: bool createIfNeeded(); bool generateKeyPair(); QStringList listPublicKeys(); - QString signWithKey(const QString& text, const QString& key); + QString signWithKey(const QByteArray& text, const QString& key); private: QStringList _publicKeys{}; + }; #endif // hifi_Wallet_h From f72a94e195036e9295b3a1d346463d7c28e88f62 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 11 Aug 2017 17:28:50 -0700 Subject: [PATCH 28/56] 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 cd57c0706a785943212b09a159121aab26d73598 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 11 Aug 2017 17:46:50 -0700 Subject: [PATCH 29/56] 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 b4b592cc00afef617c1204be775243d64771b883 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Mon, 14 Aug 2017 12:53:10 -0700 Subject: [PATCH 30/56] one key file with (for now) both public and private keys in there --- interface/src/commerce/Wallet.cpp | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index 6f0329b8ba..977fe0fdfb 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -24,8 +24,7 @@ #include #include -static const char* PUBLIC_KEY_FILE = "hifikey.pub"; -static const char* PRIVATE_KEY_FILE = "hifikey"; +static const char* KEY_FILE = "hifikey"; void initialize() { static bool initialized = false; @@ -37,16 +36,12 @@ void initialize() { } } -QString publicKeyFilePath() { - return PathUtils::getAppDataFilePath(PUBLIC_KEY_FILE); +QString keyFilePath() { + return PathUtils::getAppDataFilePath(KEY_FILE); } -QString privateKeyFilePath() { - return PathUtils::getAppDataFilePath(PRIVATE_KEY_FILE); -} // for now the callback function just returns the same string. Later we can hook // this to the gui (some thought required) - int passwordCallback(char* password, int maxPasswordSize, int rwFlag, void* u) { // just return a hardcoded pwd for now static const char* pwd = "pwd"; @@ -113,16 +108,13 @@ QPair generateRSAKeypair() { // now lets persist them to files // TODO: figure out a scheme for multiple keys, etc... FILE* fp; - if (fp = fopen(publicKeyFilePath().toStdString().c_str(), "wt")) { + if (fp = fopen(keyFilePath().toStdString().c_str(), "wt")) { if (!PEM_write_RSAPublicKey(fp, keyPair)) { fclose(fp); qCDebug(commerce) << "failed to write public key"; return retval; } - fclose(fp); - } - if (fp = fopen(privateKeyFilePath().toStdString().c_str(), "wt")) { char pwd[] = "pwd"; if (!PEM_write_RSAPrivateKey(fp, keyPair, EVP_des_ede3_cbc(), NULL, 0, passwordCallback, NULL)) { fclose(fp); @@ -209,9 +201,9 @@ bool Wallet::createIfNeeded() { initialize(); // try to read existing keys if they exist... - auto publicKey = readPublicKey(publicKeyFilePath().toStdString().c_str()); + auto publicKey = readPublicKey(keyFilePath().toStdString().c_str()); if (publicKey.size() > 0) { - if (auto key = readPrivateKey(privateKeyFilePath().toStdString().c_str()) ) { + if (auto key = readPrivateKey(keyFilePath().toStdString().c_str()) ) { qCDebug(commerce) << "read private key"; RSA_free(key); // K -- add the public key since we have a legit private key associated with it @@ -250,7 +242,7 @@ QStringList Wallet::listPublicKeys() { QString Wallet::signWithKey(const QByteArray& text, const QString& key) { qCInfo(commerce) << "Signing text."; RSA* rsaPrivateKey = NULL; - if (rsaPrivateKey = readPrivateKey(privateKeyFilePath().toStdString().c_str())) { + if (rsaPrivateKey = readPrivateKey(keyFilePath().toStdString().c_str())) { QByteArray signature(RSA_size(rsaPrivateKey), 0); unsigned int signatureBytes = 0; From 170d2b186b45ce0d22be4517c44362dd41d4d75c Mon Sep 17 00:00:00 2001 From: David Kelly Date: Mon, 14 Aug 2017 13:48:09 -0700 Subject: [PATCH 31/56] url encode the base64 signature/key --- interface/src/commerce/Wallet.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index c7ebc9c96f..dd1a463237 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -207,7 +207,7 @@ bool Wallet::createIfNeeded() { qCDebug(commerce) << "read private key"; RSA_free(key); // K -- add the public key since we have a legit private key associated with it - _publicKeys.push_back(publicKey.toBase64()); + _publicKeys.push_back(QUrl::toPercentEncoding(publicKey.toBase64())); return false; } } @@ -219,9 +219,8 @@ bool Wallet::generateKeyPair() { qCInfo(commerce) << "Generating keypair."; auto keyPair = generateRSAKeypair(); - // TODO: do we need to pass params in here to make sure this is url-safe base64? - _publicKeys.push_back(keyPair.first->toBase64()); - qCDebug(commerce) << "public key:" << keyPair.first->toBase64(); + _publicKeys.push_back(QUrl::toPercentEncoding(keyPair.first->toBase64())); + qCDebug(commerce) << "public key:" << _publicKeys.last; // It's arguable whether we want to change the receiveAt every time, but: // 1. It's certainly needed the first time, when createIfNeeded answers true. @@ -264,7 +263,7 @@ QString Wallet::signWithKey(const QByteArray& text, const QString& key) { if (encryptReturn != -1) { // TODO: do we need to pass options in here to make sure it is url-safe? - return signature.toBase64(); + return QUrl::toPercentEncoding(signature.toBase64()); } } return QString(); From ef5863d169d20a29851c0d86d70b7c1958855527 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Mon, 14 Aug 2017 16:24:50 -0700 Subject: [PATCH 32/56] warnings squashed --- interface/src/commerce/Wallet.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index dd1a463237..04005c37e1 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -108,7 +108,7 @@ QPair generateRSAKeypair() { // now lets persist them to files // TODO: figure out a scheme for multiple keys, etc... FILE* fp; - if (fp = fopen(keyFilePath().toStdString().c_str(), "wt")) { + if ((fp = fopen(keyFilePath().toStdString().c_str(), "wt"))) { if (!PEM_write_RSAPublicKey(fp, keyPair)) { fclose(fp); qCDebug(commerce) << "failed to write public key"; @@ -141,7 +141,7 @@ QPair generateRSAKeypair() { QByteArray readPublicKey(const char* filename) { FILE* fp; RSA* key = NULL; - if ( fp = fopen(filename, "r")) { + if ((fp = fopen(filename, "r"))) { // file opened successfully qCDebug(commerce) << "opened key file" << filename; if (key = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL)) { @@ -174,7 +174,7 @@ QByteArray readPublicKey(const char* filename) { RSA* readPrivateKey(const char* filename) { FILE* fp; RSA* key = NULL; - if ( fp = fopen(filename, "r")) { + if ((fp = fopen(filename, "r"))) { // file opened successfully qCDebug(commerce) << "opened key file" << filename; if (key = PEM_read_RSAPrivateKey(fp, &key, passwordCallback, NULL)) { @@ -220,7 +220,7 @@ bool Wallet::generateKeyPair() { auto keyPair = generateRSAKeypair(); _publicKeys.push_back(QUrl::toPercentEncoding(keyPair.first->toBase64())); - qCDebug(commerce) << "public key:" << _publicKeys.last; + qCDebug(commerce) << "public key:" << _publicKeys.last(); // It's arguable whether we want to change the receiveAt every time, but: // 1. It's certainly needed the first time, when createIfNeeded answers true. @@ -245,7 +245,7 @@ QStringList Wallet::listPublicKeys() { QString Wallet::signWithKey(const QByteArray& text, const QString& key) { qCInfo(commerce) << "Signing text."; RSA* rsaPrivateKey = NULL; - if (rsaPrivateKey = readPrivateKey(keyFilePath().toStdString().c_str())) { + if ((rsaPrivateKey = readPrivateKey(keyFilePath().toStdString().c_str()))) { QByteArray signature(RSA_size(rsaPrivateKey), 0); unsigned int signatureBytes = 0; @@ -262,7 +262,6 @@ QString Wallet::signWithKey(const QByteArray& text, const QString& key) { RSA_free(rsaPrivateKey); if (encryptReturn != -1) { - // TODO: do we need to pass options in here to make sure it is url-safe? return QUrl::toPercentEncoding(signature.toBase64()); } } From 1c273351933424bcae61f277b8bbcedfc31d1753 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 14 Aug 2017 17:34:32 -0700 Subject: [PATCH 33/56] a couple logging fixes --- interface/resources/qml/Web3DOverlay.qml | 5 +++++ interface/resources/qml/desktop/Desktop.qml | 5 +++++ interface/resources/qml/hifi/dialogs/AttachmentsDialog.qml | 5 +++++ scripts/system/edit.js | 2 +- scripts/system/help.js | 1 + scripts/system/snapshot.js | 4 ++-- 6 files changed, 19 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/Web3DOverlay.qml b/interface/resources/qml/Web3DOverlay.qml index e0689e614d..a1fa2d2641 100644 --- a/interface/resources/qml/Web3DOverlay.qml +++ b/interface/resources/qml/Web3DOverlay.qml @@ -15,6 +15,11 @@ import "controls" as Controls Controls.WebView { + // This is for JS/QML communication, which is unused in a Web3DOverlay, + // but not having this here results in spurious warnings about a + // missing signal + signal sendToScript(var message); + function onWebEventReceived(event) { if (event.slice(0, 17) === "CLARA.IO DOWNLOAD") { ApplicationInterface.addAssetToWorldFromURL(event.slice(18)); diff --git a/interface/resources/qml/desktop/Desktop.qml b/interface/resources/qml/desktop/Desktop.qml index 3dcf747113..ca7226a6ab 100644 --- a/interface/resources/qml/desktop/Desktop.qml +++ b/interface/resources/qml/desktop/Desktop.qml @@ -41,6 +41,11 @@ FocusScope { // when they're opened. signal showDesktop(); + // This is for JS/QML communication, which is unused in the Desktop, + // but not having this here results in spurious warnings about a + // missing signal + signal sendToScript(var message); + // Allows QML/JS to find the desktop through the parent chain property bool desktopRoot: true diff --git a/interface/resources/qml/hifi/dialogs/AttachmentsDialog.qml b/interface/resources/qml/hifi/dialogs/AttachmentsDialog.qml index 12e8de3bfc..76484cf8c7 100644 --- a/interface/resources/qml/hifi/dialogs/AttachmentsDialog.qml +++ b/interface/resources/qml/hifi/dialogs/AttachmentsDialog.qml @@ -28,6 +28,11 @@ ScrollingWindow { HifiConstants { id: hifi } + // This is for JS/QML communication, which is unused in the AttachmentsDialog, + // but not having this here results in spurious warnings about a + // missing signal + signal sendToScript(var message); + property var settings: Settings { category: "AttachmentsDialog" property alias x: root.x diff --git a/scripts/system/edit.js b/scripts/system/edit.js index c141c7cd52..7ee6c64858 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -1228,7 +1228,7 @@ Script.scriptEnding.connect(function () { Controller.mouseMoveEvent.disconnect(mouseMoveEventBuffered); Controller.mouseReleaseEvent.disconnect(mouseReleaseEvent); - Messages.messageReceived.disconnect(handleOverlaySelectionToolUpdates); + Messages.messageReceived.disconnect(handleMessagesReceived); Messages.unsubscribe("entityToolUpdates"); Messages.unsubscribe("Toolbar-DomainChanged"); createButton = null; diff --git a/scripts/system/help.js b/scripts/system/help.js index 1265a5597b..9ab7fa3fb3 100644 --- a/scripts/system/help.js +++ b/scripts/system/help.js @@ -61,6 +61,7 @@ tablet.gotoHomeScreen(); } button.clicked.disconnect(onClicked); + tablet.screenChanged.disconnect(onScreenChanged); Script.clearInterval(interval); if (tablet) { tablet.removeButton(button); diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index 37618253ee..df5ed45fed 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -764,8 +764,8 @@ Script.scriptEnding.connect(function () { } Window.snapshotShared.disconnect(snapshotUploaded); Snapshot.snapshotLocationSet.disconnect(snapshotLocationSet); - Entities.canRezChanged.disconnect(processRezPermissionChange); - Entities.canRezTmpChanged.disconnect(processRezPermissionChange); + Entities.canRezChanged.disconnect(updatePrintPermissions); + Entities.canRezTmpChanged.disconnect(updatePrintPermissions); }); }()); // END LOCAL_SCOPE From c08fce967f4f483c2bb66eb6efdd82843c463c6b Mon Sep 17 00:00:00 2001 From: David Kelly Date: Tue, 15 Aug 2017 08:58:16 -0700 Subject: [PATCH 34/56] forgot a warning --- interface/src/commerce/Wallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index 04005c37e1..4b89386c3e 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -46,7 +46,7 @@ int passwordCallback(char* password, int maxPasswordSize, int rwFlag, void* u) { // just return a hardcoded pwd for now static const char* pwd = "pwd"; strcpy(password, pwd); - return strlen(pwd); + return static_cast(strlen(pwd)); } // BEGIN copied code - this will be removed/changed at some point soon From a6390edf4639f8287fe9b8e48c588cee0910f182 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Tue, 15 Aug 2017 10:10:48 -0700 Subject: [PATCH 35/56] ugh --- interface/src/commerce/Wallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index 4b89386c3e..8a81faec49 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -15,7 +15,7 @@ #include -#include +#include #include #include From bddce9328bc66b529016eb713ebae54a02686360 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 15 Aug 2017 11:08:03 -0700 Subject: [PATCH 36/56] V1 --- .../resources/qml/hifi/commerce/Inventory.qml | 6 + .../hifi/commerce/SecurityImageSelection.qml | 266 ++++++++++++++++++ .../qml/hifi/commerce/images/01cat.jpg | Bin 0 -> 64005 bytes .../qml/hifi/commerce/images/02car.jpg | Bin 0 -> 100983 bytes .../qml/hifi/commerce/images/03dog.jpg | Bin 0 -> 115650 bytes .../qml/hifi/commerce/images/04stars.jpg | Bin 0 -> 87586 bytes .../qml/hifi/commerce/images/05plane.jpg | Bin 0 -> 62060 bytes .../hifi/commerce/images/06gingerbread.jpg | Bin 0 -> 76195 bytes interface/src/commerce/QmlCommerce.cpp | 8 +- interface/src/commerce/QmlCommerce.h | 10 + scripts/system/marketplaces/marketplaces.js | 7 +- 11 files changed, 295 insertions(+), 2 deletions(-) create mode 100644 interface/resources/qml/hifi/commerce/SecurityImageSelection.qml create mode 100644 interface/resources/qml/hifi/commerce/images/01cat.jpg create mode 100644 interface/resources/qml/hifi/commerce/images/02car.jpg create mode 100644 interface/resources/qml/hifi/commerce/images/03dog.jpg create mode 100644 interface/resources/qml/hifi/commerce/images/04stars.jpg create mode 100644 interface/resources/qml/hifi/commerce/images/05plane.jpg create mode 100644 interface/resources/qml/hifi/commerce/images/06gingerbread.jpg diff --git a/interface/resources/qml/hifi/commerce/Inventory.qml b/interface/resources/qml/hifi/commerce/Inventory.qml index 298abebdab..7a5696e1d7 100644 --- a/interface/resources/qml/hifi/commerce/Inventory.qml +++ b/interface/resources/qml/hifi/commerce/Inventory.qml @@ -45,6 +45,12 @@ Rectangle { } } + SecurityImageSelection { + id: securityImageSelection; + visible: true; + referrerURL: inventoryRoot.referrerURL; + } + // // TITLE BAR START // diff --git a/interface/resources/qml/hifi/commerce/SecurityImageSelection.qml b/interface/resources/qml/hifi/commerce/SecurityImageSelection.qml new file mode 100644 index 0000000000..be6b15173e --- /dev/null +++ b/interface/resources/qml/hifi/commerce/SecurityImageSelection.qml @@ -0,0 +1,266 @@ +// +// SecurityImageSelection.qml +// qml/hifi/commerce +// +// SecurityImageSelection +// +// Created by Zach Fox on 2017-08-15 +// 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 Hifi 1.0 as Hifi +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import "../../styles-uit" +import "../../controls-uit" as HifiControlsUit +import "../../controls" as HifiControls + +// references XXX from root context + +Rectangle { + HifiConstants { id: hifi; } + + id: securityImageSelectionRoot; + property string referrerURL: ""; + anchors.fill: parent; + // Style + color: hifi.colors.baseGray; + z:999; // On top of everything else + + Hifi.QmlCommerce { + id: commerce; + } + + // + // TITLE BAR START + // + Item { + id: titleBarContainer; + // Size + width: securityImageSelectionRoot.width; + height: 30; + // Anchors + anchors.left: parent.left; + anchors.top: parent.top; + + // Title Bar text + RalewaySemiBold { + id: titleBarText; + text: "Select a Security Image"; + // Text size + size: hifi.fontSizes.overlayTitle; + // Anchors + anchors.fill: parent; + anchors.leftMargin: 16; + // Style + color: hifi.colors.lightGrayText; + // Alignment + horizontalAlignment: Text.AlignHLeft; + verticalAlignment: Text.AlignVCenter; + } + + // Separator + HifiControlsUit.Separator { + anchors.left: parent.left; + anchors.right: parent.right; + anchors.bottom: parent.bottom; + } + } + // + // TITLE BAR END + // + + // + // EXPLANATION START + // + Item { + id: explanationContainer; + // Size + width: securityImageSelectionRoot.width; + height: 85; + // Anchors + anchors.top: titleBarContainer.bottom; + anchors.left: parent.left; + anchors.right: parent.right; + + RalewayRegular { + id: explanationText; + text: "This image will be displayed on secure Inventory and Marketplace Checkout dialogs.
If you don't see your selected image on these dialogs, do not use them!
"; + // Text size + size: 16; + // Anchors + anchors.top: parent.top; + anchors.topMargin: 4; + anchors.left: parent.left; + anchors.leftMargin: 16; + anchors.right: parent.right; + anchors.rightMargin: 16; + // Style + color: hifi.colors.lightGrayText; + wrapMode: Text.WordWrap; + // Alignment + horizontalAlignment: Text.AlignHLeft; + verticalAlignment: Text.AlignVCenter; + } + + // Separator + HifiControlsUit.Separator { + anchors.left: parent.left; + anchors.right: parent.right; + anchors.bottom: parent.bottom; + } + } + // + // EXPLANATION END + // + + // + // SECURITY IMAGE GRID START + // + Item { + id: securityImageGridContainer; + // Anchors + anchors.left: parent.left; + anchors.leftMargin: 8; + anchors.right: parent.right; + anchors.rightMargin: 8; + anchors.top: explanationContainer.bottom; + anchors.topMargin: 8; + anchors.bottom: actionButtonsContainer.top; + anchors.bottomMargin: 8; + + ListModel { + id: gridModel; + ListElement{ + sourcePath: "images/01cat.jpg" + } + ListElement{ + sourcePath: "images/02car.jpg" + } + ListElement{ + sourcePath: "images/03dog.jpg" + } + ListElement{ + sourcePath: "images/04stars.jpg" + } + ListElement{ + sourcePath: "images/05plane.jpg" + } + ListElement{ + sourcePath: "images/06gingerbread.jpg" + } + } + + GridView { + id: securityImageGrid; + // Anchors + anchors.fill: parent; + currentIndex: -1; + cellWidth: width/2; + cellHeight: height/3; + model: gridModel; + delegate: Item { + width: securityImageGrid.cellWidth; + height: securityImageGrid.cellHeight; + Item { + anchors.fill: parent; + Image { + width: parent.width - 20; + height: parent.height - 20; + source: sourcePath; + anchors.horizontalCenter: parent.horizontalCenter; + anchors.verticalCenter: parent.verticalCenter; + fillMode: Image.PreserveAspectFit; + } + } + MouseArea { + anchors.fill: parent; + hoverEnabled: enabled; + onClicked: { + securityImageGrid.currentIndex = index; + } + onEntered: { + //thisItemId.color = hifi.colors.blueHighlight; + } + onExited: { + //thisItemId.color = hifi.colors.blueAccent; + } + } + } + highlight: Rectangle { + width: securityImageGrid.cellWidth; + height: securityImageGrid.cellHeight; + color: hifi.colors.blueHighlight; + y: securityImageGrid.currentItem.y; + } + } + } + // + // SECURITY IMAGE GRID END + // + + + // + // ACTION BUTTONS START + // + Item { + id: actionButtonsContainer; + // Size + width: securityImageSelectionRoot.width; + height: 40; + // Anchors + anchors.left: parent.left; + anchors.bottom: parent.bottom; + anchors.bottomMargin: 8; + + // "Cancel" button + HifiControlsUit.Button { + id: cancelButton; + color: hifi.buttons.black; + colorScheme: hifi.colorSchemes.dark; + anchors.top: parent.top; + anchors.topMargin: 3; + anchors.bottom: parent.bottom; + anchors.bottomMargin: 3; + anchors.left: parent.left; + anchors.leftMargin: 20; + width: parent.width/2 - anchors.leftMargin*2; + text: "Cancel" + onClicked: { + sendToScript({method: 'securityImageSelection_cancelClicked', referrerURL: referrerURL}); + } + } + + // "Confirm" button + HifiControlsUit.Button { + id: confirmButton; + color: hifi.buttons.black; + colorScheme: hifi.colorSchemes.dark; + anchors.top: parent.top; + anchors.topMargin: 3; + anchors.bottom: parent.bottom; + anchors.bottomMargin: 3; + anchors.right: parent.right; + anchors.rightMargin: 20; + width: parent.width/2 - anchors.rightMargin*2; + text: "Confirm"; + onClicked: { + commerce.chooseSecurityImage(securityImageGrid.currentIndex); + } + } + } + // + // ACTION BUTTONS END + // + + // + // FUNCTION DEFINITIONS START + // + signal sendToScript(var message); + // + // FUNCTION DEFINITIONS END + // +} diff --git a/interface/resources/qml/hifi/commerce/images/01cat.jpg b/interface/resources/qml/hifi/commerce/images/01cat.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6e7897cb82e3c8319ea81e291a57a00d25429b90 GIT binary patch literal 64005 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

)2L(>Q{i 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

ixGKT}rFU@JX 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�*U=@b@jUrhjcVaIi&|_t~nwHVn`MZJp(k2zvc1# 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 P$OC|l*ZKWNAP@i9?%5+X literal 0 HcmV?d00001 diff --git a/interface/resources/qml/hifi/commerce/images/03dog.jpg b/interface/resources/qml/hifi/commerce/images/03dog.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4a85b80c0caca0a36b23bf92a15c39bff23b9891 GIT binary patch literal 115650 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 z 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

m=wwBiVQw!YKaI%;4<^vamv zxZY!Lw{5?~B&@R#nskB!7E`_4^*wVWS~uPvgCRIY8OZlJq2@fTfa6dNOg7zX|>>7g;iKqEAZ09>ihih1pzSQjskp znv&0k$e*JaQRfeyV=rWS+l8qx9_u(1FEvg7;|gLx^ti=`>Voe48V9+*HvFjz^0Yp~ zn-#*;gOb(9nz1gE@XlQQXp}_)bF}Wx7!*x@Twej8!_|P4X;u6qfr8hN)5$iK*4CxH zGRAjU2g)ddsKJ?HT~w9tL*;Fyyv>7xS#XMB0SSPURM;&O){~<<30Ir`_Ht%W6lsv~#%!a91gJ2Y>na z!*aSa!JDO8m5n|Ih65?1N!LG>hPDfK5gE@Gi-B{g>H~R02@)Hx&gB7M!`JbOyuk6@ z{7X-vc8RKy*xaPd2-G? z0{LdgR_b|ayGAN>L8Rwm)Rs1gRrhVLvGcJ0=58;;KJDG9gZo`FGA}&@uiSOu?zz@R zug3-dkraJvD%)nK;Ejf%-uSeThnh}XW*-ry`HT-jK40GhD;1T5Tp<|TE@sISTEeP9 zhW=zZ+yL{8kY>S&7`640RHs0>;qY zLA9h&ZneFct;YnL!=}K>pA=;&kXnIo&7*Tt(|d-yHhEg}nZ+Dqyh9Vd%%p_QaaJ|^ z2&0b`Y4a+T0fdm9Vvr)+iDmaC`Ok{IsP^ubpqi%aX|0W7DGzmJjg&&K-j;=Mj~g1R za@4w-bb2YN=_bM(Wp3wCVQ6ko>uzPF_eH|Ano8#%NpHQar=G$*UHKBs2mU3=3S1)6 z^94s|lEW9xRS>KGS)5u(+6b?(^OxVFXWC!?>qU?1fTV@gQN*8#tUm(Dun6AiFC;Um zhvqD1mfq3HmDq>nxRwZZb2-n#c?*BPIL_NMe4(s+uAx@^AQKbs| zwT2h}mOc>R(^+bRHh2@pP@b9Kq)gq^#(A+hbOg*KY8Qu~Wt(R( z5e%I#{UplJ-Y;ZvdcMh5epef|qT*oMx2m`0ON$5F-UZmmBoTGT)4cl3O6qM&YqCNj z##~!$+JD4XwpCb9Wb|*XaUi)eS#rw4+d@#zq(uT-Da-m*(8W0}?WEbU4-tQj(X0gS zq&iC;K(zozMIG3oTv|Y>#A(r};>wuEu3TRxR32@aXZ@ zpA@(u#k0c|*knElJ37DXQOV-6pK#Piu}Rk} z*ZH?gHt;GZ-CCuZs~oro+N8N=3FuwR(xN9w8EXLjPZWvc{D{3VO5m?UB&dVUVbj0M zw}f6TQ>1jsYWBDjiV4NF90z!o0hV0j5Bt8;PwMzdCz~RdbM}69t)G$+;xziD_au1+5aMc z3Xx818+aB_aJ;Fb$6dbtHzXn^f3QF-uRn-nt_0Ah$}BIdxiAx^?D80-3{!3L{ z8+OeytqAjk5z{vfRV4;(Jmmu^#7S`> z<>1|3FZgAygKiR)?zR$AMQeyK>Rd;)Qe>E0+Hgf~L)lLt8`rCia1n}iFu3!K=q_3*{CzW&Q7@gd zWflIMBi~#lWXw_5{svF`jnKc#&EbtOS@_n^?ur`L@@cOQsX&Hw!SrQB0&-H~tB^^F zQUxM)9!@^|tuy^%;zSsb4_%U3?)kxrUEVoGxJ^2cvFXs~Iuw`@XbUh0(`3!+xEVhj ztRQbpIY*}aNO7{_NYg|tScy?(r8$M-ZsEm$QMsZt32|ee*b2v5HtXx(@QAD!3c)U) zuh#(U`F?B5nI}TVed}7V5>+fpLC2dCKg;-=bCn$j|1@~xLw5%+-i9Z;;L40%Rs187 zy;70L3?zg8ycoekJ%BRGHH!8Qi!$Zx#yD}p{j z`Y9?JtaZ|duDBbFk*(YC?hKz4rl1ikT_1bKM0cM!z<%6Q$U4K_kWYhuN9Bs`0^_N|M zKU-h+B+7Vp%^yb41c$jnj&CcDHTKyh$@UG4< z#blzX@Lf$bGLdnf&N|EoR;}S z_u};wFT}8=1u}d#hz4%1>tu17IF8suJTQB7w-es6-Z6PGEd9#Mb3D^F%iy5ppv7_Y zs!-hN^xz-KhfkF|k$Tdpl(puV#;8!GIu1`ZS;J?6#K#Dkx>}Qt$XV)F*D`Fs<|rUu z<)QZq#Ym9RfR|pi;T#fK>t!me+J=EoZ!Gj6-`G@GB#PKut?NFC;YEu2|E~Yp85bR* z4!PdT16XxCN{7Mvs&)Xs{F1}XVH2pdaDZ4|V?0)8G&3(4xLKIh z?v@xWHvGqCD!<~${R}u^luCtB&aRLw{?$_USoKwRW$x%qSbNE>j#07Vv+NA{v>Y0o zRSh9tuK}56FYsW3d*DK% z?VI*voUo8A{%kkdFX{HK^5_xG{aVYth?}!3e#6fY-5Njf~4YX#p&?9|0 zCX%@@#P)_QO&H6-VVfB!((~d2^{ax-5z*J4c%P&puWu#NQ{+^q64@y1#ZQd^jkg2P zY-z0cV1HiJ;^ILOhYgxhsrL@M0Y-yHzRLh0)nU z)RxMW(hRw7@V`uZ1-$tu-)K48OeA+uRjbLjOe_7koV?68HGi8!NPd-9nH*eHm1xln zHCopR{x?vt!9~=0F%6-qm+NmoOZo%+z6L3qii{9~)uHa&(_#jV4K^RQ>o(CS z6^(D0A#e_`mq`XZIyd3ku4Lrsnh|9atjbyT=_Iu(PJ(G`&b7L+iE-ik?zkK-W*(AX znyN~nROq=5FoI8pGGk$$0_JTL6nhKxDa75E{1s0{t95rW=2f%DZkbE95{LgdWD~$U z#TEjE$@ZyS+^O((%$MAb1KH2TD&JFp27xf;?%eDR>42F*<=+dj>G4*WCsdi&lGFSH z1QJ7F^qLH9+c$6UH($Du!)93w?CTCTTTZL8)0J?!TgH8SBTc?5?_T@FJ`(O;zMrRp zHEtu=DLay9N%x~)#TE!m{`)grEa?d_2)gtvfm%V4qwIKmM7tecVG0Uwhbi zj$$dpw^Y%VQ|s6?C;u@VI|!r_+{_XIeF;g&DY4A*9SvFSn#Bgl{iy#j_m9N?JI1jd zWc+iXk0LrCEW00BDA?q%W?yv5?3^84KogSvY2q29y}psQ8RT;ka~3ssWNWg%J$?o} z;C~Ov@xu>`C^Sm|_`hQXB)cOXkaF*h;OSkt5J8lx9$<3A*@^Dm1ua&UC}RNJJbNRK z)@!koya;|y=dJzJU`AV3f7-z`XRW;~>Q8i63=5}51J*oG@j%h8pn$@o}ei{Ni2dIhanC=P^3xm zT@oKkvX1G><5O?;eW<3G_!*_I`oSdzQW?M{CQ0gjtBolA8P>#5ZA*iMA^Cyym9_q?pg@WvLkA4e=V z-DFG-i>U@T+Besyv1*$ovgX#6^&GPmL62Q90F~L~YpXN~V@ zKvegL-<6?&a}%s@TpXX)nNQ%)Zw_qzZ3mrZSMm`ku`E>q80qZV5LbctYY1-d{N;ck zTBtO@Dbzt_)e2KMmR<%pO!G}5D+>Cw{W4itoX}EPT?B?n`uJD$yO$nzP_(<|T{XMp z)hyHKbGKA-KEoK2E1I>OB7?=(Y?zaHcjLrP_CPO)#bjK(sSmaHPNpS>4nO4i^_X>3 zv6HI)ELl|M6rs&Y@6L^GZ?t7|Np44it?Y5yb4XV*mN`qbp0zj9=tl5eP+???m1U13 z@B=f>Jq^rJqujw2iGXESuD!@xL{ zQcmzN+4^2sMsH9#o0r>EoPrNOuYI^j6G(DQ_>%|&-3i)ljM~*4&rVl-X0T$?Ld?xf zHtuy^an|E4;YC%`x17ngiD^36zm<~U^C55_6nj=2Ap_?W!+Nzd5~cPay6$qh0l08) z+f3nRT7bT2r_nrfZq-1?JlHC4chJqv2K5=@z5B3b$AvP3-QWs89v5?=7cu)K#oS|3 z@5i?)c&$o#WuEQjhoW z`6FI5)KP9vS4%nnP+C1GUw@k_2j-n_-vcqxf)2=o*rVH!^D-GCnC?CW1g+te)^e+$LElD!;jnq=`GJ{Wd`b#owg#Z|{!br@#SLoQ0rub-sZx7P)Gv4Qeeb=8QF~*yR>cf?H zZq1S(wj=$}_K^WWsAL89=#Q;yIno^!_eO8ykJ|_5TtR3(v=97x{kwK&y^MqW#rilR z82``=W~E`Qbh~Zd+1$SsxTw4BkM?=ZDXzgI!C4Gw%{sVlK!GF@7$FP%*_aQ;C(?I) zs|#|tv#>2w9TuM6?o(F)JtrG8{*31|S>%(D>?R#WskQbc#(n~v$N0<5`acqR3=??r z5d>E+9TZ47idTB|LwakPAtAu8VteQ~R!`Mt-5^xYi;0$RK1iru*`Pabb7l0=#fI0_ z{t_pPa8CR%8JplyePsAo*$-h?!*h#S-w(@IOx+BYXe-is%)NcY!o>Lt7%m$;AE7cj zHvL75VwX4`@%_s5y2K?4_Kshk?R6|?V-a5`^;;MINL-FBb2@PjodkXmsRHh;!9N*X z@e86Y*D_@u*ZY=ZSCRuF8H-2%;2>->**{~p#lvINt@->om4JuNTA>S+G(K;E0$S6s z;N*yb`4dX}4b!bT_}usJeYqkh2Hg38PbaVgF=j6J>r00@B~HOCJy6&jg3LFt>rlC{DC2+FRCjXOm(kfH5RmHtiG(> zrtwuTkCCtB)5aHe9wRPP8lg;F+|iOnK7|l0KtBX$VKw*mQ%qiHlC0SXe%+U|q~Iu| z|H@jNI~N;0Pq`vd6*?v1|4hVc+|>R!c<2#vYDp^iM^I8fa^{uu^1zAHD~)uQmwQL(!%(}SItciI>y5-ZFL z9eAG9{wYOnIIXoUQGvB2aL$Q#R6kGwp`J}m7?J9~Kh@ThJ+%zs+0=QQ;Hec$!>2Q> z0352QaQ78@U@JVucQy;(i?mJfGSg1r$cguCcv8J@zb%-+#LQ}Ffl?PH7IkjC_Ubzv z|0?Dg2F7_6otvfQjgE`hO_sXuXWP+kb_OAaY|CsQW}vT=IHSUp=ukK?1wEV2QpOer z>|#yBw5>akakN8K!oI>%rKn{DMIz)-4x*dF!rM2pVpc1~=iL#pC6*wJLgGUc z?|2V%a1rkybafyX`~;)8hHgO}42=F(iOP9Z4Ia33wY3l_lNMODn=-6+Ib-9GhRTsb%kP?Hvz;R=-yy0_I4BIQ>^*@q@FR}hYkLO9dzQ`MR zNwh0M@Lh&25>PM9S1OeIoEDCzD4ozXy3|6ekDgqcDZ3KLnV;uZs*nvS?AxDhQiB&L zrz)6zo04+i>nBt`>&^BRvHm+US!PI!w3As1nO5EzTqK-f1FRP`SLt;Ik~Aj^o|3D? z${5lVO;7WllTSHS6~Q-ab1T@*gStypqK6iyG0n|aPdvN|cfUY!qtUlQJ@X+b#F8@U z_j0dojEK%pWKoh*Mj7FLS2jdz+gMnH3DMYO`*&M3m!xw_(&R*MK4${ZG^>7hYz|&z zTY5)GJ*LMfsD59vp)R49uuI>#CI7f;>-TBWXj9EiWy_`l&cpO8`M78Wi*$XeM+LDQ zlQcF@U)}iGX95CYc4us1JST62o>A!C_hjiK_*I8cH0O}QR{!t`JL`-jYG=LLLGQi5 zC+S#;@YY}hWADg1J)7*IzdKwW{-J-IoxV#zpRPSvGNmhc?+PvO4T$HCp#;|Q+*s=H zo+%ylh-;TiVwMy2*8L$0xQ zb5-`_g15UZ7Hl~dT@&oD?Y|AH>06X8qP%3N3UW=U zjLdCn=??-Txap)`VfQlyfV3(B8zbKGHkmM*U4JXcB*B8-V_OH+G3ilSd!123eoL-2 z8}w<$p|>%PKd1cGM!Cm*sD13kRG|Cg-!CyAoGdQ452IopCSzV!h%`CRG|aFV*Jlh! z4Sr%qA)yEzdToO9Fyc$u{){_Pg=i|b)w)P{6?hqOm6oAiU{dUefApuQqh4(Im+h%a z_-t=a7!GVJf2xqmKbPtou{Sx?zz{h*R4enj7=^%p?yl{=9M=Gl4!ruCTpR-F)FZE5 ztqM(z^dFi!#~g^18MM$fh9J!rfzm|7#_2FWDt@j`B{5`Z&~;|Vx8{cigdn4~vxuK1 ziwraYN1DGLV7i2J@2~0*kS~t_>I@d64Pf8rzshU+ej~UmN=C^hMau?GCcd`~y}iUAGi^rp%w-g;8*d9}Zw4jCnJ`-N~WZ$ijV4(EyULf~V8Wcr_t$ zerAG@sl)}gJn><2$4R(V2piGHb$MNtvW8!m`{xgD)_QqgAQ?W#jAkD<>fu$&#QtFB z#uXrtSU;@3E{jX8pzU#F1br=AcxKi4J@RBH_3h?4Jo*JZq7$1Naaun6xJ)Rk7)M*i zZ+8CllaE0g5h>hKEo|uEu+XFT$;*D@au@eV?U+(mX6G$ZkAcC{*cSAMq0Qi2?9e8& z5bBTBp5|=r4^po;c{zcVU_bUq?liqv7%csPU(;a0Q|FP;oDNShjj+>ShbD|t4No)B zJO4ZWx3Lb$l8T`;`wSl8pT&`hh{qym&A*;o?hVf1Sp`)|^S2jke?l$jHg%hDSD zSog6oyGLu34Kbc~jRs&Puhp&{rHD%==drKF3Pw($UVfbZW8+2SVwg z$kfn9D@}mc0@{%<5L0EEk8dusOgfU>5Ig7-Pi$N*+9|eD&rPjjo64bbzIzxP;wgT1 zcP?v?m1U-Us_wIgZJ{$h%ALTw3k2I|&M9#QXSm{_b^l1j_I0U2S>{OGv}-_g5G`}Y z@K;+Xx9$20_M7l1u_QM&K-aOhW>5{SeU$0y{$ZNJ>`opw9p|JSH5u>d{fZ9(dGqNZ z`{2oQnL#(7l<fUh#yV|X!bkTk^OQchAuV*}<*ifu^dZL5?vhcF5R_PuLS?6N zV2voP13kM|`Jg4OZXR+Q^O@MzW#tU-fiwku`)6hFU zatkwTYr?whj9fSRP8u90JzfY*1tp!5%Pk2+vj}Ef{IHZx^I&0Ps&yLR|KlG)vCI6O zNXh37)0i3kv*A{YfC8<-Uz5=&xCNgohgtqcei4z)=Dm=_<*)9*osrE0@;ZV@d!vVr zbs1e!0^{7aZVr&a3G~v8Jl)IRPv#Kvr`CYWv}pIRpJl$5vmh z_7#i$SmKAx62U9uLGKUmmxlC(h6^{C<$cdKF8u%>d;_6#ev4)a4gR6F*S`X!dt@!t z2}t|wEavAMMXC99F705Dm5o>k(ApA{WoWDywv_639s7^OB+}iW!DR4iu+HVHG%vPF zxcjznHwh8U3d0VZbQ*K@XbY4G)B@+D62ntP5ZI_ghHE1Dga!C?Ep4b_dB zF>Tz$CrAt)6B>^~%_Xtek2rD;sl7Cf4M-d8f1R>CpQ$`Q^V4K&x%{*hJy zB>sqwyy)_#WD$Cl1|+4f(fSO4HNiC@OUn{sYeOHM7;VL ze%vj{CXbUlXVA^o-B`%GP$J=Py;_UgkI{j*HA}C|KGxBwB-JuUJuGfM;*yBmxhP+e zaq|_^ZYdddtR8mvwsYj8b1zBwP5ubmS>A7 z3aP4nAyNrN1iTX{B>!BW@(x+??vpkFkotNA*2JU5PdF(J+ws_F@>6J30C{9Xy7lXJ znzlv=jk@?QSC)vA&bl-_{1R&R>${<%rxI?T(j6)(Q9zGN2o~W}eZ6#>@_H%p}UP-a?LWRDBh5B@E(<`WP8O5yB?E((P zxsi#~KmpxJc*~JD^9egI0AIp|O;M8kA8RSuuAJug+u<63S} z^3Z%DJ?gKSdzLnV(GA_TG9Y8R5c~Z!a)#T%azsHpx!LNW)p*%IGCC=<7K2 zaE96Wf(Lkjl6Rl<8b4S$hRvK=2RVFR>z?K7l;t5N>#e=K>H2F zSDxS`$DhnJp*}^r*Uvb+t3V;>pxt}}6NZ@6sskgWTM(5zFSHdZJ%UM_&50B;3d_H1 zwO;tpcBd)?Z+v3?^GRXVJU74>T8ng7dW~e88rCTmN~RtCLeZ8hNd|_=T0(@1bI-pt zq8n;9pWAC&l;6hhXp^03mK;J_VUZ`>Z>UKn3S7|p6z<@u>QR3sUyWz%CX;|t1g)fF zClp6-(n&Cdc@OSeo{8K|+UkF7liU<$@Lm+&Ysi~!;-b{`c8F%c#0>}?FL|(a-iJCw z!a(N8q-FfqWYLm0t6qBX`m^6XzAA@%$^Mif;ZCy+RPQSL!l3^1dBSpZshi%}G_0w? z-QVH;BKrR8F4^zy-|WA4?8MVG)$i+6GuOB4ea)$05i>h}a@=l2lr5O}Ojv0aHYXJ0 z8ApJ0bWZZ`BzLWhfmH=GlpN!i-+vfayfCq#MIG$al+4Gi3dRr5LLutSU^$}e{()W_ ze=wsNzd#eL4p($O2`zZ)5!y6Umx*UNZPSaTlxJ=sfv9W2HfVwa25>$ObiQmsv-!Bv zW*)jm3DJ36uh%YY1PwH_ z8_6x+){1>t%um$K%lUlbejJRDx*uZtLs{}qS${T_^OrwykHn`l=lHW~BmHkOt&U;` zH*fyVb<~Z4=f`%uqeiiUpOGW+>pxX#Ey}LB;5qV*e2(5-tAa3m*KfDtKBGWd^DMq9 z4O?6t>t7vw0Vm_}z7pIt(zHUi<3(K*rrz1Y!7v{;VJ>#}eqOSuC0E|UfrpMQ!MzM1 zGAmB#EusJl{8?a9B>OKfg9 zdG9eRATyctf$iYF7vSzaYLEg?`%9@|rooJdHPRW2my#`*kXl-;ore~aK8D1w@z1dZ zjiBAIDWw?oV=Zif;|*Fn)P9zEwafwy7da<%P2ANiZ;JY&SJ5c#Untp6%-z5-R)WN= zbP8uDym0G?;8!j1GB1nQWyI^r&X!rV;_S+im-i65H>tC^+TIH%NBv40cwQS5lbU{u z+v4+=K>9HmJ(M%l>=fg!!nq6ExwvHRj*v@x9;}%pjv$=lw581ACI?_K7tze@IAwGd zccu=IOh6t!(wVgp@$6V^BU?B&s$@bU-`F83)%FU}SP}Ik-3jf6)i)U@xL~P?!heJF za%etIU94mDruSML`>Q<6ZHyWWlTX4*xSAWmHQU+0wJ3P%JtDl2wrm@9AIUpJyMn$Z z_z4N{$<;@uM zPt})6w2cno)Vn0hKAG*+n!X#i@FJ&pJofdCvS15VJR*ZpMXks(%cUT~8<_Lio8}89 zZ3mJ%+gJbf;__6|<{*xi-LEC8{O$2LANAr`$wK-_57Ic7BC&D;2NNt)abCOf^>|XN zW)Tu`mBqOzh|o4Yy`^*Dp#1*;|33i0`Yb-j!!ZMG9;!WP>U6XuG_Tj)D$?*&S?FX8 z2akiUpH7-`bHt)?`G_;;(XQt~tnP&{C9nouhTgh^m(lBqn(m{fE0_^<9%q?arbCmy zjz!n*Zh9L-j80lM#&&5+iKEJzFA1Bu z13(f_c7^p_mj3{>-2vPqMKooh(3LZ0%-%9wbRBk7n#h>bb)pJaL0x}~$X7=9wPyXQ zmkr~_)t3&YX2u6n&ejZJB1lOuxv_sQZ|Pnv*i5pGF_sNuK3OLsTSib7F!BkLL!_li zH@_pcz>lBaYE`r3Y~oYs-}K*+;J8KI@=ZK|$I4{m^Nuq@&K2T|eQ~1Zll9t9mf!KM zuw{E{jXe^erkhP`$j%4kdJv`vlDY9w^aV|NvQF(3ZA%qs+hjvGuFEH^C>Hiv^n9f0 zvwsQxtMIKYJZ`PirE6Ag17#-p?IQs_x~w%us;@uUNiTw`SZ~`UFO3aZJytAu{(71T z$B*>-q?|=)ksc!K=FPJ!;agVyEbfZ$Wfya#HL^Rw*>g9RT2E9P`cbo#;`u&T ziO)TGveK5(VlK{Ry2DbubmlVWElAyzX3_Tnm)m^KYqLDlo5}8aoTeu0E4E@{PLo9I z>KWQ0E|-;?N`E>mzS>8qc`KPRE*4T?s7vpQ6Rk-`bHRr8`WF}HFMpquc08mrZs9b$`g`Gf=dQ?dp^%Wlv81aIZ zw7u0KPU_}rSW}aGI?^EyPgQ7|rt#M5AP%F$E;whZKT)x4owM?pD9A|FxRjaP+HIz^ zq!Dq9(v{?0bmK+-;?z*k%K4{lIa*74of6L6}Wu41~4S!BV0_5Eji%H`=cjQ2D4s(W72%5Tg6 z08FTyaohGy-$8`)B9x|A%|pm7DWgfcQ#OEdz~#&8TW_0Eht>g>kUn?gdvb+M3rOj{ zjHF|m_pvV-G*KTudNk!nCWZ6fbJg2P{ZV=-w&-PGRMSOJ~i z&Y?pJsAx&i>nHs}H=a_#7o#maP}I z6eg11j|duMT*F=(WS*JbS&blg|eC|Gm?9yC6#90iBnL{ zDrV~Q)81=nf?F-S&EWKrohdJT!%{S0%C3Cg4h-U{Sl*GPR_Cz*^o zCwe>B>#5KQ-R=7O)qT1;TE8KNVr@$~_ZU*W=Co0KSh85rp07fwI&@;FhNXxBBq;Op z5-)W~PLX`89T?jvE%qK2XV48jmsAnY{45u&-{{V$aof5pnbbV?Q zs&j>A`dJ}6Ye`Mk%5U`S^mrOtF#S5Foh5c+u6RxNEOqIBOk()MO1`z2iSfygN861l z49N`oW-_JbiJTYFg6Zq_k+?OCF1DMyB4>VGyXI?kwL0sTy;l=Nqt8*>dU>8TH@;17 zfoL3KzIgnJd;+zzH`lg!s;-tg8S4PP8O>)!8bu2rd#dHOpF;MO3Wz9tF}R&1%V;&_ zZ)%%p&gn>fi5Tb~S?POFBcvo*CgQW5S-%yWr_s{(SO?P0Jh38yER`aqE1iJRRV|(1 zu{mmHXIdO+%lVUq{UlD$s=H;OTKW8{&FAlmyG&fw%_ZSN7J1(}8auMlv#xL)n7|1i zGT&bzKs4OgH2J4z#$^zyS^OSGg6RRB0R@YDkTOKn30TnU<@a7bCZT5?4_Z+>wbFVJ zTG;*ZeDfU@F85OAN}e(?&K5ORIorJPc}gpK+9`_p>lUE9{Vdd-&E~4eLZdsaCq!9f zs}ipFuCF0F`%A%zzNy`AK}Oe{=Yx&P8MIys+J46O5;2D!uuRf5g{3_^6IMpgozT~8 zT%$)es`>?!-+8oB!h_SCilRQ)s!{K3ro@t-Y|?9~N){7K6?a?JGh>qWSABgCUH1!* z&2u_kE~($*sbrg)IWfyqV_aDVq-E+Z>D0e2Ibis-eZ|H#9G~2tgwq+j%0nvYKKId3 z7XJIvlA?O0Ini>8voMu3&3q|WbC}Q5XM1PX`Tcg3g?*Mo;LKA+QqFss&8DZv(N^(T zq|iJQ%(JB^vXD_{aW6E?DqJ74HoDO)o^6>+zHjnQZWRp4Atz}p{BY5>a=feR13c)9 z<92a=&y_5*5y>XgRuq(=&lY4FG(Cya`kC&kI07uFBq*Ikzj}gbmDxWU@hr`rDrufF zXr9`Oa-Q4XOJ&ttW#g(Qck$Pa6q=Zk&jC~#EvhxEUgpv&rcG_sn!P15k-5$*T6(9J zPc`&SRTVRRrz)7VmqKU}^sQpLyqDRsHG}^BO0FTWvn=Fh)kO%@j&<=1oPLJlx!X?m z$l5C^YqZk3zU^E?uQ}I9NmR3}#P!IFsrCTfAInycGWDa%bsG?OJtav*McRHFp@ zl-<>(NMp+}j?!JTbthY?W~&@eHGdlAIBAEEOzhkGoW1vlw-w})r6RO%Tdu)2qENPm zS22X3>Ijp26Y9XvFCE1%AvCegiZjTh(Ju;F(V9l=(RnRg*?~nfPy;?#MOy9;>GoVz zI^8)ZT|9#gnA*}%vrb7fl*1LOV`Y-pT-!R>!szO^zIw|wCwa^8SYfB+J{QSos^Zg9 zyK)^F*#rY+c7WZUYN?^V$T|Vb?`4g$7}D6MeE3R?Y!eeUJ)ud-0!NCOD%sOdZ{LyE z;XO85$B~lk=NMGWQ#89e%GDnlj@?M(IW$iMI6#$+8^-J6#oET&)!JPx?dsKlpn807*7{bL9NL8^C=I8dp58GssJh zemiA;)HK#`%%_soXzA5(JmT9e-ko_yUsyw}UmZo`IiI(x`Q7Qp>&mznCasB^9)p>p zbfhrL$nF+24;Q#sv}nvIvz%^Uf=A+6myqVZNAJ~=@YOtgY?x_DYCfFk`sK+^DNQ5_ zZ^KDttHsKCm97jalKOKVSj%@z_FXf3)NgHL8WHe(Z$T}1^3Ug2>3vytHl&pq_#= z4N<9TeY_fC@(^7syN~c*Pn!8tbNo*>oIn2nS$HjcX9qo!j@^3g$usem;wEqR&Td0= zC%kCTC2iOrevN!|e*XZBTwnUt{UQFXd_RoYkL6zpGSBgj4>uLa`f+J&l-9U)=gZDZ zPoApxEmij2vR-^{qI~wlCD^`wd_J2Ws`Tzra%`-V1fJ|v)iUffAo<07uMMSM+Q-b~ z^!f6>%}mD0v0Qxfh>F?nW-n8!zl3muOoYyke0Sidm0m`s7V&AWTi`dzpOcPpi<;sx>*MK)su7!8&&in!W^W-jlX}f1 zq4)aM!Jd8eMJb<3WxQ8rC~h;$PkO(+Hd>`2{yH=rhdp-U zs%z8PIO_4;mr}YYX0j7>lx|U}8u7ooHF0A-OiZ4tI;>@)($@r4^Dar5#}`GE46;wg z_WoD!lv<{4JBUs!&~(C(qYKg&KZkNbw{XKhKv z`|Vs-O)oy9AGZ}`0q!+e{8c?}wWq3)Wby$HiP1;m{-Y1KR5=?8$H_+L6BM?f~M(r!>1dBt5UTQwPpG%PEg4ha*3-Na>$ zWspef6?YkBgK^1}Q%v$pQ`lMTp36+j6n#|9p&>b6l$!}QOWt(V!s%$$u9v2|Q!L=r zl5?lc6-K^N3NZo5#ge&O6)4yCpo${u7*&Q;o}b#M;tt zbuU#!);TIwmSBq z6~gkHBptK6C9O)iwwYd3yyxJtY-c2q0@z6`1LzCe#X~lMp5A9&5XPxC$(|Xn8knGs z=UPKt4s;IsOGH@GjUeb2`W4ACuQ@i{A{i!5a>A{)~40u zs^ab&QeI|cneiQS?7gbr;irbdvYwC1Ez#@|<3Yo>49C7O?=-QQ+u zY|W{P1nN6NL6NvuFxJfAUYLO<`aCmr=Lu>3LO^Da5POZ4*knCv}{|&?}&FTwA7H6QrEOK9oUJZsD#I z)t$>uE~M5qokwTL2MXXak@}X?nPZ~4)|K$jTV@M+${GNRG3vRQs&l%~_fXX{T9;W; zh_$G9o?H)u9oOWgMs{f?ZaN#)WB33)pOWKzXeufSCU03lmPaDKDO=6Vy9?C;wq3~S zr6>=O@{JDPE4{IZ>V?TMxzg0d$!8t{y4Jixz2zy| z_G-`CLp(>2X4RrPDMGT&>i*R}46km}TeXahRU-DI%Ow=itFfgy_^+y=jV3Oy`{RGD zSrITuGeMB+Nn1X7uhv3E)KL(Hq^)HXwJqzUB;tKdb3Eo|2a^wL$4$I#>I)0#tBL2l z=_#&hfJd7%lw$4bOZz?rbs%)9p!d|qrbycffdfTK@_`QHLiWREoluE`8FC=$YyOgILImZgpe$jV-`!5v` z_F6D`Mu#H8Iw_S}vUd9@A$YXVT1n*LGvi7bLG-`bo1)M-PZC;B892~kP+*f(V)uB9 z#!cPhmTgmZ&61wkQ#xQ7Yk23ppAlUIlRH9+siSB=(wb{xdy{nCCg&u}Q!VuQrZ6iwnAnaV9m4T z`r4}oogPbNBwNjAKX9!cf>WS!j>{*zBAS(y;!lz|{TMd`>D^rMtT)ApSX9Zp^r01` ztt6cEQaWnzNquHjyDdh2vQ0FzqH^PHN=#_8naID3nz{-}g9(&fFYRiy-6iT-D^Wz) z_LT0dId37qr)QQY$LeX{nX6sKNOjJc+|avIw;LxZISZnpsvmEMs%NOjGc%K`zc0(} z(2uH{W|mZxx6T{J^WcUTCiHdwAL<(eb>^G{%Ct z(_D1V+Zl%f@9HY;_T33G{w-ArJ?<)^dfr;9rbG5jYJ#aJoNO6A({)Q~(<;#@u*$1B z=+QZ$Yh_Age@!Ru(|Jv5xLGutQigNL`R7`qd!qUwU~m``*w<>T>7zP@8>b)xNvn!` z2GDR_bL#YRRQ7DuG|<#qu6{z|Ym-34(z$Zy%}afV1sbwM$S*{)Le=`J%PQz)$`z*Q z$X04BLx=)TE;8BQMtvn~x_Zt%79Nz%$LY;ltc0}63zcQ{!_nt2SAd9B5qXrOcyqE% zRFg^J#w@kjEl#MYB|DZPen&d%!YtUvGNly|LPkm%#s)f>dW(jga?fk+^KU;bmhsuQ zPm$M&sL|Dmd!w%KIrQhUW|dQJY}Ct1H8E&}8Z&<~Xh;i0P#DEnLsync`b6fwSMp z8Y@U8DUq|^Tj3mv zMu)~H$;K;XR^)A;7{RkPWg1xj0Ev%==O9<@kXz^{TK%yzUSl4Z{qpD;$+8;WbxWa5PU-brzu-A?FGPB+`8vqLqA zxAyP%&R8#&^OgBm70Gfo;VZ-O-yK{-Gvnj$BA3aVOaB0K;u5|DXVoRqY~nFkeT@z% zi{3GGG5-KpzpTGC{)l4u^f`$9hmD4=cl&=0SpNWWEYu2dU~!u)&S{HGOO3i#uYYf;1dsByZC{F@V+3JmXA((AVAYgRR`WA2;D zEOW`mKdIl-JfG9=gwJN43xKB_-Eo=yI*10U)WtEs7;dHm?>(tGh)vGNWPQD>#OC9CgpaMy6c ztoPOGYab!`-WZ+LKPAU*KW+JYzkoL3cUQ!&FCA(a)QX+hf{z;Qws6%q)oU|Xhm@(A98yIrvJ!67`^hT#btFIJ$O@X zm`ON|(`^dNJk1r+KczC<`g_F@n6Qk+%_>y+uCn9bxk(HH$H%B<;*78GogDUN_|}a1 zI2YpRxZ(2L17-NT>(H&QI@Y5TSZEfRkvf0JM~xatGu@hXAN4!pTevCkxYqmg^FpPz zK|aIeM2EIw>z?VU8jCoFt?6p`-RDU(&?$Y{`8NlaIL42R@^~ME*(oK`;_$(fpUEi= z+?{aG-=Y1>l7=a0!YQp9c#ds5t?bo5obKm2tX!WM)07)7t@^i|$aL&EW;q^1b@slU zN^(7O+vnx}A~Pq3NQK z&aO+*bE}=&=W5OD3#mr5Gj44fCi-gBkZlgjNw?@1lE~5WjA&K_D3x^QgtRoMzJAnH zTP}I%U`ibIA=M(R$fZlzdVVL&GSl06%4Gegp%ZD;s<8vPjT8;tQ`s!N(u(uAK`}Q$ zYvbf|9eNtVJ}AW~1$|ng5PPFoB<-52GP|zXYP3Tk#}iI9xnzmzsC;R+#9vJByq_us(XMpYyIl}!6~3G0zhaL-(Y2y9 zC#-7=J#m(Y2$e;PU(oa+>8T|`@RgPp%cPd0YqzTTbfVVDpebm-1g(^OiDqDW8D<&{xVm0*0q{f4XrJicB3%7NHU zy;C?y-qh%#+c>shf`EZ#tF33#0-Z9bJ^BP^Wi$=*G_N|>NkP!`biEto*#0{l-Aq`)BO_;KROvJ$3-^uhBkT7s;U4Eb=pd$)BT4bLxsuM4oJGEm5vV zAXU9KX;9_Ah33=KEc6U6TSKd=K=g`?QRa$SdmV)Xuvm0k$d)cxu_v?olAE4A&N6g( zR0x&+dR>*^Ma~&yW&Y3A)O0NmqGSxL@RA$effF^3@l>D=4*LtNRJvDk$Jt?4K z_IZDTOGTbTYfBcXD@t{7Ihb*p{p|#Gcd}4+%&zuET|s?$-kwi;nNboxZCPsZ0Lx6n zDtEy(r=eu2JmNU>v!7c6t?I3WU91+AtzT85q={bY$mj`1(8h|5{JA1@Gugi~yPjpL z9rX$l#{_r zW5uGh7ep^NeG{8aBR{y)7g1lX@k-USHH**1`$F$HxN0a>PV;hu&89K6UBqK65GWtT zP%VV~nxLx|l~!vDGE+fVq~Rr2r>UB1g^BqRvld@0&iUp}O{Bfm(9MFikdJd%_ZnUM zlphDHp?>wc)}DN0#u{4JRGg(rXYYN(%9k?B$`R?u z9eA4bqQw~*9Mi=DXjzLRDRyS6Rw0+9dUZvaofO|TYqF4{AXYvIv1O{xW}X40o?n!! ztt(1j-iE5aqN+nH$Vkg;Q8tN8)RuHmqL*(cvPQI;+|5;H)OpR|i90ff_RHBL+D$8~ z+ajgqV4hB~DK=J3PWjrisJcBapbnh*MNxE?RrU2ZwBN~zKxwazS$)Xq*E^eD$`vS@ zlz2Jty#NY1DlyE*xKyP~i&azYr!?+s+@Rb`ra|5D_LG^ zntq0yr|Z$KC}>C4$k~>E(ifMOXGe?@Aw!k=$V&k`(+tz|1^IsJKg&Sq~ z%UI_YDjr6iH5nK;0X6cPE1H-UX`O>bWxA&H^;+uGz07pSO(wdu=VrUv>t7!gm!+qY zPHNJ&w^nMoj27PSw*1^PXmcKfC#7J5`Q*(ej#x}Z1nHVC(vZzhTd$kWD@%c4)ukDg zEj;t^qgB4Rwc6ibSNjuK8WP$*n2A+^zv9m5w?c#3 z6+@`cjnE|JKAX7=+Vv|`noxSy?AB9l z=*I1P@L$wLR|Umw?q?*-++^vV!?<+;<|r>= zFD*^#U&oy&?;fim);pPs#yyznWtpR?S8oP#>8kUTc(6^W_?>`b@a=wQtK+O*J{n^&)0wYY_G>R@mg2p86ed6vu3r>M>d@nJ6l_!DL-Ul zkx9S3l1A*Iyz5hD&hPstbK-zU$-abFU_vi*%x)e~tZEbCe4T)BSE>CJf*duG=N^V8&;IIGC{ak(>cZ=tTxW;wRcV>GWE zqgt;X?;TEQt*=-hK5;I!N-@9ea(@8$XUn)Bm;V4y`Cbn!el^PIeN&j)(=5MYy6;b8 zEgy~?pRY3i0L0#PY0oOMMl#ViJZ=8~s~`Fs)0gL*=O=@g;drh)iQuo#rE)y-aU2%~ zs!7K2QO~C(blzXybRdrHsgTJctu>sbUlOhl>ZUjT57gCjf2EGEd)=@!J~_JTxv6Jf zOSN_}{bTmK$41}S0Y98HwvJw0dh&nWxd3&> z(X{8Li==I&##|`Mbg3?JXM;J=tUYZw(mnS}>p#f%{F?jguXJ*)wzXSUl`+lkF`E*$ zsA#_$EOP{ zG30wz>ate8@BaXxTK@o$;vw=bLL64=fyJF?b~ZS_!=-g+&r4|}EojM}gvUL!I4w3b zb@u2;u1~3m^m%gJV~UzGUYvZfH-2ELYH1~d=OL%3#MQZ;pDs^d>EjgT=PoxEIvP%w z9M4%w44BQCBp0gYh>5?v{xhGB=Ds(dQ)0u)Ha-uU{?mhyTf|2DXQp=CxiM_bYd;@s zw&u!C+VER!WOuHpHzS4Xbm8?|T>kZGD>QV((i&*XM8ln7#=+q95KQq#gb)nL7)2-O z^`u=zG&!lt`TgjFbSslgn<*663Y#AUM$c)+d1wq--j@Bl zVP_Q49QD-rsw|rxcUppUiAl1(>ODKNAL?m_>Y}Qt)YBynEOi78aOb%kwAHFAInufq;xiEi7Smu zFFI9oX8X?+#aPPWbXVOF!_36w`(|KWuYcDkIh#IsY!%s$PAuACpi%S7KI&6Gd1~rT z-CZf=>>-UmY{#Cof-}~?D#lw*v`Npjt!jdTx)yVh~pO`en+c?T2e&fkH`83HS1ZZh$*kgYemg`hc zE%EL+M383N++V6DthB<@be#}QN+D9x&t+`uU$&<5%4IvC&7cQg6`C+f$*uNYuI)?K zX93Q^RdXan64TJtEN!85qAY=58aumA;N|n@G?fl|>gm1{_3K9g9e$WM-N=FJfSl|oQckh*e!2pvOO!_Khpnd08Uoha&wAu3wE z0<=VGlvbblet(ElkR>_Q`9ayFyj^_->oGqc+A6P=spfrxJ^MN%+DyEuWHf3pkBO^A$#Crb#W2dbi2%wd{T1>!)qM%-xQKh2ciKN8*3U^M#US*%L{xYQ|io`OMk^)TJ zhAY?UM$y#CT<9*9PhH=?e9Ru!rg{M8Vl}1ZT_U-VJHj)I#T!CDvHG5M`m;(+AcGaR z9eq_We4hXaHNL#ko}*a5C}^6=^841feyv@`IW+t(x} z)eQ6p*%nn^(JN|B(r5AXm@D0%%6eny&|e)r`RH9TWXXR_@iVm{d=T}d-_I)O{{S#A zXiaNHX?Z8=KP2pmj3;qgw8YspDVcIhpfZx$pK`W&li=-PKWsf7RsR4C)s!VG7~59b zC=HhOYvH%5ArfOms<$LlB0?FnCflU%NUXH9{{Y5KkJLK2G_|C%b1#y7nJlbxVjAt@ zX0-9C>o+&2#n{19QR1d(rsz8P!BdkU?xd-i@iVKb=16)jdgwt6fUK!%4Su$hk7{{F zb;_QG)YB%lGfEN+ba;%@fw*3bO${vKDt$va9-$dOk_BXvto$PYhqA@o zPbN(Q%aN!JBKHWM=2nGF+PT(`G@HsQYHvd7lR#?pd3fmQzK%aLrZG$2b!Mwps)?d$ zp|c}r1cDqTG@+ZSPPT;E>Y?>L@SzOb*kme%8Y+HLfbxgTve^=AX*0=EqMp!WcMSIo zgZh5gnfUy9sN#t?RI>G6;jm$zXTFe5s*KUeVuo4M+=0=g6_Mlp5oiT$)J|An^|G~Ur@+z-4qobXMEan2fXM4dseU>)+$T|p!+We_Pv z*LeD9-NrKVbW7cOM@bf4F11-2k`;%lpGyeRnkZ1C<;dD%DRiBf+NxEIE9TaD`(ZOY zF+#$(OGsyg#hxqvSZmU=SyC@bO;J&%^$R#9D4Dc0eeaLRC0f#)t?8QI9&SS{ zjats8Z`%!%OvhKLk(d!#befuIrK=k23fYPAj`D8T%*8cCH$`7(!0n^0Ow6W4HJEri zP}Z~-_P6<&S6!X;(@xd5gX&eSo`(C(KhDfq9%x9oX3MgWlKYNkwA!@Ig*0+dl=FG= z=PIQ*{MMr`X<4Qyg|eB?@2e)3VZ8H=4IIyAqR$%~`PIa;Pd#T^y%i&5r>`)(sW3`r z2i-)tK^2mg%EYgYA2R6aY%3=pW$D@m()QD13YGG0FWdhB_mWvp!%HN~8EQg=7s=#| zba5#x(G`7FDt(H-f4o`n%B4Q!Oi{-LWS87=wTh(Y97NB>-OH)cJ|@KBiD*dCos{RM znd`HudbuK0r8VEpVq|#wO{H4-vi+Y#s9e!4?~U_u{u8Bx0btDnuT1YnD;QUjYhGavXBy;Wr zzIjt`{5eo*N&O_$nxiDhX?W&~ttii1%}vcK*F!&}AJs#`_8_?)Eut75f zzO6Uab$UN_o_Fsi&P+Mz8OU1vI`hl8ebrDI9e zG$XuvrDXCbXtD9x&x7+ZHN}r^Zk1y8qO|gv{Y?T5TQqVcWc+;tQn}>!-IF$DYGw^R zB?7gVw5f5Ml2b#*MpD% zHvD6smM=K9p4znYx#q}a2xQeAayw&cI5W63#c*0`3d zM3^x2OUxl4P&W{i^`Q^GuBr0y0Xx;_>U{Xm};LhmbxV5 zT{!$njI}5Wwp8|C-Bg^c6f;Xb-Z5(goFa8-{axQM{)p4!+?J1!LyR1@SFawprO4qr z-ka~TLp-$Q+HgbatMSi@^L%@8Pd&-h$Ef9MkDR;5KJHhI;yBpyR^>JAmlMb3&YWza zdTzb==y45BLr>Em+~$~TPDL%Bi^BOWox4GULG>P=HZEf7hUR^$ImncFDy@mP`%lxI zxjNjXCj{d4o{!YkWygj}nyN9TS-2>IW^wko_P(M5IG~Nyb#8s~aq_Pc@~qY0BEshJZ{c zk47l!Wc2fh>jpO5O-n@t#Pj9yWL9~zt`6pB z)+#Reqo21Ta1RT254CGcJay;Er_}Vh@O#pgFD}{bwVrNg7p%V&CpAkml4hZVfcq$G!#KLs)m;QHS3z)VnMdgE z<2FxoaV|@^=8NXbs=qFoS2aKrS65Wh^tBYZi>;`Z5YraXo*<;HlhtTd8te^@rFfW= zA(?2jg{!_s2iIrDnkWf}wB?g7c?5R+Y9S^GRD7*Ad7yi>ONuy~xjSrEqItF2s%XlW zRGj_lRswk`Jq*(blaemMrQPHfMjjc%ydNbi-n7obXtC6@cGa3W?GkF}-)~QX64Pd{ z*tJMv07_8$ph2h9Uy4p=$C<2Kb*Y_>I@X8fKU1c@Ji3lU$GJ$g!Sjh=;`<|MbE;h} zbzIHSHMSR()360%CnW!Y7_ zYZSU43VaVec%kG6r6kNe*w%Auk6NchHG;>sMW~YiA_VV8_jplQy(UpJF^yk3gsS?>xMX5% zFA~g?v^8+_?yq^RQ>u0?LW;h`@RNf-^0TLkvM6yhqnC2%DDq1LaM*F2A^DM@B*!d(v;D^O4&`^}PL0aD-lGi_3yv6R z@3|dnwj585d;y+q-sX+-C{-gsifFQvCq{v1In>O!RV=RvYKJNLIC(%WoWpOz{LujQ6E$`*& z3*czYd%8_zzO{7EAZHv9tJkTl$v!^oQ|q_ws*=@EN>nC!I)zZ5mq4PGL`P_GuF!JI(!DT(2GXsLpBzg_c6Y7+G;MOiT=85y_YR#nFkN*Hjzr=Cj55fNcPd-V=azAbc66Lq?oJ2mqg&R(Rw+nMxA)*J!WK_)2 zv$H)Z5}v9xgDoV|`8@K#PPL2@zIu6g{mq@}b;eA~{*CJWT-|y+7n5m-$YdeMBL0}w zVV@%=L{15j<*B2h72_srG*nMClCr`?Qs{Im7@?#Ghno8g)UzWO27Xd+2PspEax0q9 zK{OVu=*s|E{rX&%w3z#;lordPi<$EfMvT$dk3JE;k2N5kGg>}$owX-~?1&5QY1nBj0)Ifp3xNPV`rF`Q# zzmD^UmiYewJHm6N<}G&NxjsLXoO2Wtm!6EfEoEY?e5E?9{Y8DPKzsc<(FP_?TAf)c z#l3W!Xe4N#x^(Nh$=+2IplYgEJi;MQ8u~p(R%)XpkjzyU<+S*kchtz!Kpz3yODy!I z%*8Wh`}1`ZFBqWGRnHc6sfLk{bM_O>*1BbqUEVSmjO*+sa(4@!lhH%eTGJ{dipeyg zrkMoo*_L8#;mcL_UG5uQX6?HN&WOD$XsA1bCskCdkZF6_shxvC zvchl$w9$x@{k>MQq@ww|t^EC!rCduSQgwRBDqMl?qwC?_8dpW66?SK)S%B=Y^`_*z zjL07H_vzHh-E>mgO-)(;U79cLMbq@sfVYxQQ>#q?u!RyP^rY!*@JabH#u^aRJ}{aO z>hbDx1a(Zbv(D*SHxo@YNY%bdih9{tz|&jDk0oB`sCJD`G2uf~2e%U_#RR4_H=$N; z-W!<>Xw9Cq&^#rg>oflV94e%*c6XKgFD~b!(J~N8?jdbEI;O&WYvlZ;_2jZ?*U0(H zHVm2-cJh0N9mIgi$ETUgtW%AaWRaS_G)_DZ9PgR2(t3Ht@_Hvr9QLki=1F<2D50pV zk%9*EXkD%wLld41pyr7>eUMF6{T*?frSY{%v6U9G%dO=yc0;s&Wx+ks%${#A2tE2;6VRh!z7PFn z&G7#Kk#RR8HvGCY8rl}ZbY%Jz;;#$KlfsQ$4?VfZe&p1e@oKFVlQzjMW6RHt{NGF{ znl*wMGcK2tYOX}mhotw-+Kr*iolTyIbR_jf+cl{Q6rHPYn4R2Yy$+I`Wd5~vDyywr z=+px?&#NtrrzI=WQTFG}KQZ8%A{6y`gsv)vYEUbnuBUS~GHYz@+>%oyg>0?A>E5o) zkv5gZ%{rQupNBM!(Ie3kO;%22=t5T9{{X13>Mz5CUO91S;@402D|zuYpOstf3W#pc zr!SX|XANlxN?R=@)ffYE=6sL&{`OrJp9Ng=z$WvB=~>P7_|}l8xmGfdZj>}#XlFvx zHCm%*lSgO&0II($rrthy>ey}*?8yCWzFJ|QHg=w82=DH))9Sx0p!mW)Q3NmkK+LFhm>fLRq^GNnUM-9oHNP_ zXO$vO_9)60?uUXJMNz6_xip6h&Okdf!%|c#EdZ` z#_OxDeHCI^@q+IU)BXGkwI@nCmuqt#jXbN=eD9iFJ;2}gujZWfMO7x&a(TeR*6w%0 z8nY)?HYli{Togd)*B9k(-|KXBA9@mKjC`3oee*A#Lt@*{AmpmtLuB82P;6Jet7Mk1 z;%C~M@XInQIVA_txiUQ}Pt*L}=6yZd5lMzalXZU8jrUd`J6=fGlNg$*9Fui-u6d!l z8e{=iT<$kIIMmH-yIYakbF0Y1xywOl$BN%h|G#i0;$%YTp6q3Pw(<114mOl zLzq{l+Li0@3o0 zfVoY7`@e&exO&%%J;&zegDLJhy8dz9h(%A$~?Ki>DM(K6377DT$0s>sSe z1XW#3$5wS+4rf(Vcil}KRKl{v2ZzxGQw0`ld_b@~i@D24Zt=HwD&-~orK^5E>kyED z{q4U6;d})r$q{9<-r!*z%ztb4xwZWFtHJWl=kKC#X`)-dFT8B~-N*K5 ze{&MIs%|O0DTA+}9nzVwsUH3-n=eucomz&XBTd$NcEYMSGDb&|rAyhDe>%rE)P>b4 zvwT{ga4vV1;f?Yf#jXYJryf}_dH&sffw)7*aKz*0f^7eHz!g)W__MgTe!^ARXnW?4 zaHEgMSQxH3bJzBg6W?{gk(@9AQZMEc1nl9q$4N#Ia02|WT)X-k(-_)?<5A2S>wZJa z5e#G~nkt`OOimh*6}a~md)*BJtPljs4e&e06n&p*NFVQBqjPodmlHCb_kVzDBEet1 z)MDopgUzaUn(VH1iQFrc&s$OmXcnv;Kk~G}97Dh%4Fb9#0KY^WZuxZN=NL6j=&=@f ztsj$O>WcdY3T}(`4TNubkNhJTrYxjLdOxRDw}H1|3L2=?TK{3R7zBLAFZtx!c^_qcPX$u#o#UIS=G&e$UT z6B|AX4ZLi0bDUwN;jH7WFjD7$jIu*=Rv~=s4LFet9J{hZ5|0CCRX5_&MGvM}AON#* z@9kFgv1!!MT1zY23A!WMDS(nno@ZhBl`zM=dtlhE4CXZIt=TMcp$k)2cUI_-M_=@_ z(4kaVlD=Jxz5mcUPcAJ|Z5;xtkh}eKN7^}W5)&kLG1b=?pz^(maymDK9*PmV9Si}g zFj9P7EK7svUi0||kP8#p{MPxbUK0F3@3{f&lw5~mBI8Me%dQ;a49$WrrzVWa#lRC| zR#X@dO)miMKljEZaNgS-Mtd2y_vJE=sBc9t6WqI1i)DdNLxS3R@XKj z&x(9SgaE`I1S}Fy5Rh}TVW(lf#a;BFN@T^{&eM?ZuMTpu1Zy2fcNqGja@l)iA*N-`J|8g z{}#VIeEDZB?4yitRP=|HE6@LO{C5GVHPNI`-70_pcLtWU@OYo*yt|y!1Lq>Q90hRV zc`O4b)`R^Xz_``59JIU|;fEst(*H+R^cQLW156ZZs~iFotA$XYb)!M6xq{3Vc&lVhdevGrB{WkV4Z6zVSrPDv3Eh@6+R6g?VRI3HO zn}+Py(AkD1JJ3~r(dE^>C8A?>mI}UnU*t>k?ApEX2RMr0VtSNOb-F&GSn2!Igdmv^)p@%C}pWLNiP82FPQ6UdL4$_icjD_F9$Yl;77r z^!863%}=-63rj;!iG1Hv_FL-VdU5XT=vUXQg2I11N}cx!<{oRRwr*wjW&5gL~6uui}5F{<7M{LGI>rzGV|Jz7r=~6dn_%9y*L{aL@jdd4xT`i9M3E$fX zWx7ySEb&yslQ2Rf;!gdGoNl^pYjCf`)4cfi{Wvx0&EXFXuDZ_GJ4-Lx`f#r( zi8Ds@CQ^24rL{f$p9SAcxw7W*Wesd?E9-dDQUa%-U-griLy4A zQs>|)sSh~fXE=?592*G3tA^nnBo>WH^OTJm>aM@D<-^-*CsOB;|Epg?)>X(J`~Gvb z%(3@;ptQV!a!V(82n@Mc)6vof+qmZVmyGF)HrU3z#S?|%kpb53sb|;sNG^R{z3_wE zFXX{s!PLvL0Tz#fz^AnZXAfP+bRW-M%gbM8;X6=Vjr&=_Z(8bIsbE!AzO)iYb0Xfb z%uLHZTgwjtyun(}G^y?l)wEw;aNdi-t{Q!QL#J+?KfCIr9oNInD=$9$%}hrXpFE!_ z;NpVukU$%R%T{=8YQ^lkd>-vfH8yz4JnZqxG4@!ZdIW}+(6(*9?OH#p#?GHSM>e^! zed-oDaYDH$Td?9uvwsM!Jx5I8&%n=$!Y@??Eqax&eEtjjafCvMJm23d$K9nEExUZ; z5`hh+nuTDmmCGtA9fAK?rGY(0qq6{7?SD@1v%)a7OLt_1)qs@h@fuI7zlyg>Rg!km zWA=T8(V%MzUMS_|opUyMVA%4>`seE!`Q9ow)U(1cyhF#sM%9@o^2n>9&1vMj17mmU9LwaZogUd2 zJT1gfW4kq7zpPjr^UBmed3WFNzHnnNu3V^lx2$16$&*y>oIT%1F3D$6M1?fEaeg?J z96ZFYeZ)|bNH&6ihY4fe);OEtk=m>aHim+V1#sl&O7~zzecF*xXUzLCMAyq}aRjA( zK|<>-x9!T=bnIHZNINFF`5c(Z1PWU*6$m>Pb5V zZ@~#)cU6Vd2k;{BIZYzZo?314{izA=oRW*GI8H&XHrSu5*L}B1$A~`lY|3Crz>SOF{mJI_WBG4VOv{O)o8VyjSXQst(>yaE1c6B4Ti6;jZ)_>G)BMroa@Wa>(xV8WJiOI{hiGPjfh5u1LsC|I}%f)K_@Fa0z*GS8AR0^g8#nhJB@IHU4_jMC4mjf~Y@LDfr8| zuy@KVVej>|`_y<@3E3jQgRjZo)6(XP&YG+9v34gA(MR(6FIHV@DLOLUY?g+CmajjY zpDzKwy}68K^LdcJzem6u{?iCT4s+b z#D~LpP_rQ5KY;x!F$G|N2)00qQz}`92Ft-}GRc~}e;in(^%k^%#BOn3I%EG21hk3m zXUs$lF7H#Ev5p-WMC)2Ljd7s5%u7i{SHe?5;CLoc9At-pcc1|x1tYbKG4e!hK>!K@ zV8=NaHIZ{$A=7V!F>fgoxziA^_XiBs1lcvwdh@9hULFd z#Q-rfAu!T0+X>3Y*VF zRy~gnv=;m(8|)Zk2LZjL9SAsPV0IW(qrAG_iaD41Kd`lmB^&DeWMOi~A$Mp~{53|@ zpgC7q4g>@yEgv$1zCpl`gL-|bu<+0b2&j);(UJ%y4y^}sadXWaOzqQ{SJl>bLqtKMgH@j?#Sxh2XmJDD7oCP#RGIbH>o6n+IIs(RS}fctW21R{ba zR>6aTk!EfkU?4yg^JhzPJ#86tB?LetIQ1}e#y%Ym+E5v2PPiXZGdP{GH-K=vq9)a~ zJ1yNDc_~2sK@f;BH;iY%j%bugP@UMtB()9y##>h`F>8YVtaZ^LKtvss?$eu(#N>1f z?+;25MHtv^fb;S@Q5Le3%cT-~M6~b)2*|dnJ)RywLH z4+1(z&L6|+GBl9&!k^tUogK&CC*@iL>5KqPHvHc+Xg+DF4jOn`Y+L=eJBWy3gk4>G zeGCC)RFdifuM6=YGzca%yn={86X98mrpyWL{bRlx*Sk9Kq@_YeV)z;}aDuuLhy^nc zUu*v<(yfC($=%;c+E6*0+-tCByUel)U*EP3&96Fl%F7~mlkadR%=xFmz}1$ZO{AXUstU8|LS$kjtuI%WA0~5d9|{RI(s}=)6ID> zV(RKY$RdI>DZ+~1XTdjEKGAT*+o>P)bW1kjBpaoiFxS@OOFp~H5`NgbI-OoGhkzFx za24!IIcUgjL;fdOdNQidbnkLjM1WrK`Jb|<`7fq6eQMJ-$=bZr-Pj_YIj^d9+w)Z) z(}(`Ote;OQsvA`l<3&*MO+IV(qeiAOO{rq+tiYp*f>yMR-;&fl`&ysaw|oL|Pjn*n zKC-M98aDbp4FZRW^_dt0_j#3>LwV<~W@V> zw9|{+2clG?EemKykprQl#+Izy{g3IV&bM94Nl$RzVMOE5_m}PtKK+IxR4QGR)h#?b z?$+IYS26R9m~Mddrh$m!CpIS+*CH3(kOt?>NR^bcnJVi%MNC`~Xk0O7bHn&&>(A8?JCM zCM5ypZ*!E2%T50J-B-JJ<;kmo{aeDu2%6h+iQ~iOzKaWA;(2oXY^#>mKGf&&tMa?` zplY4Goz5(v6ZisE9D`*;nwNhf*Hg{?+FJC?YZWUm>-ce3ePjM6T>4e+6M^-dx7_Q) zgti;pzl1gsj!+h<(ibLMgl(v>0lG^Sk zL?v4Hqou`57Uxz$NdpgP8IXHUfI-xZ^^WNva zDgL6Tb~#1wa=#wwXyz(61lxSoIDMsjH=1~UwgFe3T2GxGv$AD3-wP-GP<&buKc2Yf z8+{(99+}u|_$6*eAVsE8FlHNQ3Wf0^Ov}-j*%K=WpYQYGGiD5p1N?&rbiwR5yo@kjQ^IJ z*Q5zrbE_E!3{+mjRa^xHzlTLM`1Zdxajt3l8*w&*Pfq>)m>Fla0MhYwR=|T>blEbI zaQWU4C+-8lD>IX!r`0}WV9ESkkr8pa_ZYK&GL&f6P%rU$R4&fM#BwxP@q)o#Wq|27 zK#4$gmr*MlcP2OT(uEN3dq{bGKhgUX|)O)_S=_7u~n6 znD^sYE)gTnW8kcSBN>w`w5wqY*mS2!bV_%3?Y7=|boNp(a5)~mCBletQalj)!$=qAByRkyk6btX)5QGG)u&WETH4*8X5BEPCvd;*E)Ji}E{8 zv3!&h6c-5E?aXJds3`K1^u62ZnyeSA^v%^@vt484M3$~Yz}XHUWF5_}NBm_coD1hx z|Hw<*`j#86x3L2OjXU%;X1J#KB8Ck_B(^f}ty@F}1gwxjRjD1y(*7K*m5r+nwnksa zE>X!4pwS2-5ZFQ5IZQPK5UF6O_ZlNCY!6qyf+TL!nGF=YDurnq1_7to&XY3c4>Td5 zuA<8}F&^L`h8gH})0?_;0zZf&`lBEfKpgThyb(d*#eXCT)kbyAi5^_zwb5 zzaQ6lqx2!5#Aj`7%?oTf+$Z*7Q%X76=l5PCx_9lm>_y&*wP5c-fN+V|Z>r@=6FF~! z*%8b;WHDRN%|gbcaD~COYWQy~C91py>F1nfh= z5_yg|x4*(U4*^`*3I!|?wu&KdFb-7>b&yGXN8{hag4Dz4Dqw&(@;TB80>p@ib70I8 zjllu|bvhL@=*owtQ#oCZ1z_7+3(-3)a1y;JtYV9q;UW_ufC2$r<90^HxgGvA*zu`d z7>L0$AwWkMGs5t6+&{ojnJo}-iieTB(~Lhr?Lk021Y|6VAH0SDd$gt)4Ic3a)P$?d zqq+2$hm@!`2mr|^S!DkvnYFELbDX`ziqJ6BN065G(=s!YZf;HfahzcDmx7m?bK?K7 zJ2ElCBC&>Dzx>dR(ur#n$NUS#$kWeg>j9?`sY9@WIaSdAAF`r3C&1kbHL!nJhn8M* z2vV1#ma9TQOFsl`(eaK&@WUZQxZ1Mxas=5asTD*>5hoc~QZ8nRh5)mZDX1+P1TaA@ zrc-g@8g+=eRfWW~qeBqO5O9J9004k)hNXl!*}I;0l&KtN6#1n3e=Hhz|)6@J^5CDwSn922kly(cr) zIp6#tI-adY3lP?gA5k6zzl-3-<=&rU8;w#HF-A;G_$q5mV>4_I+FNff-&hChcW$|A zTG3J6h^>}}t;!)rAlLx1uX$*|8+A7?CXNN18hyiRF-osiMM$bAZp zj%9zxmKa&aJq>{RGBQl`Fu&f%6(UeZ59n{v?7x*;oZ)pY4dYw-a8;Zg0;-%ZN1c2i zPMQ=IhHcQ0~B#Ie3ug=oi3cnTmKuFAYI@;ZNze$gI0nUyZr{A~s6 z$nQp4hODe2taG5SVpQsfX=q6cG@#ZQH5C}rk~z(q+Uxb z1Gcn7UV;GMsXhy%xY`kd&a6qcNy2h=I4z)Jn{7S=$0<(E7ONMenA3_S=}PA*3lnO- zZ-)N!V=c(9+WY$GZF}HkWC8UU!-j9&2sgh>N%Q(04FRwX2{V#b99{OB4{JEPbDB+e zI58=dsFU!>Jslo6avlN@$rKcQi+O^!Mx}uW*yqjlNKHSjm!EGiV3Nxz?6%2+%lNqp za>2-4b4j(*wTB~laXY2A=}IkVMue)8gZ8w20BY)LA-UUF!Z+-LS+lD3=TBZ{xMvqT zOZc0F4o_)!91a?ul&8$_6z6t^KiXy9EZWj&hxG`9PgORyzVz2Ysa3@H_eSciP{DT*f!dmNo0`hG+7Z_ zAmR@MkcoTxay2gqbU)sM90;Iwq3y(@X6LrKoczhQ$rKcJ^rORz_1Cta=}H{`EPfTz zQamjrqL6bJ;s_|kes=8km$9HF{G4mlLNSej3rYH-2J2?F7-_M+-34-paGs@Yb}V&} z*@sJIi~eQ-h6_9+AK5z}b7e3o;T+;A1uaC=@AKC&ffi>G(VQW$6k_;e>@kLYht3v7 zV>*121Mj858kq`ny9CNQ{{Q!$tT>#Ib8J&K;-m>HNVae+-j`mc7Ne1{UW<1*Ps)w2 WNkKqormk&|hOnpGsWDp&H1U7TW4_q{ literal 0 HcmV?d00001 diff --git a/interface/resources/qml/hifi/commerce/images/05plane.jpg b/interface/resources/qml/hifi/commerce/images/05plane.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6504459d8b339a2937c49c621fab2ff36f75e9ac GIT binary patch literal 62060 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�@erMX9QdI%z?_->1!uBNO3lR61 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 literal 0 HcmV?d00001 diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp index 63bfca4f31..4eebb0fc39 100644 --- a/interface/src/commerce/QmlCommerce.cpp +++ b/interface/src/commerce/QmlCommerce.cpp @@ -48,4 +48,10 @@ void QmlCommerce::inventory() { auto ledger = DependencyManager::get(); auto wallet = DependencyManager::get(); ledger->inventory(wallet->listPublicKeys()); - } \ No newline at end of file +} + +void QmlCommerce::chooseSecurityImage(QmlCommerce::SecurityImage imageID) { + auto ledger = DependencyManager::get(); + auto wallet = DependencyManager::get(); + ledger->inventory(wallet->listPublicKeys()); +} \ No newline at end of file diff --git a/interface/src/commerce/QmlCommerce.h b/interface/src/commerce/QmlCommerce.h index 0b1d232fd7..5653e4ec98 100644 --- a/interface/src/commerce/QmlCommerce.h +++ b/interface/src/commerce/QmlCommerce.h @@ -35,6 +35,16 @@ protected: Q_INVOKABLE void buy(const QString& assetId, int cost, const QString& buyerUsername = ""); Q_INVOKABLE void balance(); Q_INVOKABLE void inventory(); + + enum SecurityImage { + NONE = 0, + Cat + }; + Q_INVOKABLE void chooseSecurityImage(SecurityImage imageID); + Q_INVOKABLE bool hasChosenSecurityImage() { return (QmlCommerce::_chosenSecurityImage != SecurityImage::NONE); } + +private: + SecurityImage _chosenSecurityImage = SecurityImage::NONE; }; #endif // hifi_QmlCommerce_h diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index 9378a1d95b..3e86063dd6 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -21,6 +21,7 @@ var MARKETPLACES_INJECT_SCRIPT_URL = Script.resolvePath("../html/js/marketplacesInject.js"); var MARKETPLACE_CHECKOUT_QML_PATH = Script.resourcesPath() + "qml/hifi/commerce/Checkout.qml"; var MARKETPLACE_INVENTORY_QML_PATH = Script.resourcesPath() + "qml/hifi/commerce/Inventory.qml"; + var MARKETPLACE_SECURITY_QML_PATH = Script.resourcesPath() + "qml/hifi/commerce/SecurityImageSelection.qml"; var HOME_BUTTON_TEXTURE = "http://hifi-content.s3.amazonaws.com/alan/dev/tablet-with-home-button.fbx/tablet-with-home-button.fbm/button-root.png"; // var HOME_BUTTON_TEXTURE = Script.resourcesPath() + "meshes/tablet-with-home-button.fbx/tablet-with-home-button.fbm/button-root.png"; @@ -217,8 +218,12 @@ case 'inventory_backClicked': tablet.gotoWebScreen(message.referrerURL, MARKETPLACES_INJECT_SCRIPT_URL); break; + case 'securityImageSelection_cancelClicked': + console.log("ZRF HERE " + message.referrerURL); + tablet.gotoWebScreen(message.referrerURL, MARKETPLACES_INJECT_SCRIPT_URL); + break; default: - print('Unrecognized message from Checkout.qml or Inventory.qml: ' + JSON.stringify(message)); + print('Unrecognized message from Checkout.qml, Inventory.qml, or SecurityImageSelection.qml: ' + JSON.stringify(message)); } } From 04006a9f76047f6d65d1d34b181732148aca73ed Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 15 Aug 2017 11:19:41 -0700 Subject: [PATCH 37/56] 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 3a8856fae6590cc7d38334eaf37451c79aa7bf25 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Mon, 14 Aug 2017 15:58:28 -0700 Subject: [PATCH 38/56] 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 84738f51c27d24decf5c8e1ebd78c0aa036485d6 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Mon, 14 Aug 2017 16:03:12 -0700 Subject: [PATCH 39/56] 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 0f7db74ef12d16debc448016b3ce31ad7cb6917f Mon Sep 17 00:00:00 2001 From: David Kelly Date: Tue, 15 Aug 2017 11:44:15 -0700 Subject: [PATCH 40/56] missed a couple warnings --- interface/src/commerce/Wallet.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index 8a81faec49..7a980528ce 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -115,7 +115,6 @@ QPair generateRSAKeypair() { return retval; } - char pwd[] = "pwd"; if (!PEM_write_RSAPrivateKey(fp, keyPair, EVP_des_ede3_cbc(), NULL, 0, passwordCallback, NULL)) { fclose(fp); qCDebug(commerce) << "failed to write private key"; @@ -144,7 +143,7 @@ QByteArray readPublicKey(const char* filename) { if ((fp = fopen(filename, "r"))) { // file opened successfully qCDebug(commerce) << "opened key file" << filename; - if (key = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL)) { + if ((key = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL))) { // file read successfully unsigned char* publicKeyDER = NULL; int publicKeyLength = i2d_RSAPublicKey(key, &publicKeyDER); @@ -177,12 +176,11 @@ RSA* readPrivateKey(const char* filename) { if ((fp = fopen(filename, "r"))) { // file opened successfully qCDebug(commerce) << "opened key file" << filename; - if (key = PEM_read_RSAPrivateKey(fp, &key, passwordCallback, NULL)) { + if ((key = PEM_read_RSAPrivateKey(fp, &key, passwordCallback, NULL))) { // cleanup fclose(fp); qCDebug(commerce) << "parsed private key file successfully"; - return key; } else { qCDebug(commerce) << "couldn't parse" << filename; @@ -191,7 +189,7 @@ RSA* readPrivateKey(const char* filename) { } else { qCDebug(commerce) << "couldn't open" << filename; } - return false; + return key; } bool Wallet::createIfNeeded() { From 6e0ddadb29e6356f1e42d6872a774b66149609cf Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 15 Aug 2017 11:45:22 -0700 Subject: [PATCH 41/56] 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 528d2072f90cc0e2b54c511ee6a5ab97d5ca1069 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 15 Aug 2017 12:14:32 -0700 Subject: [PATCH 42/56] Bugfixes and improvements --- interface/resources/qml/hifi/commerce/Checkout.qml | 5 +++++ interface/resources/qml/hifi/commerce/Inventory.qml | 1 - .../qml/hifi/commerce/SecurityImageSelection.qml | 7 ++++++- interface/src/commerce/QmlCommerce.cpp | 6 ------ interface/src/commerce/QmlCommerce.h | 12 +++++++++--- 5 files changed, 20 insertions(+), 11 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/Checkout.qml b/interface/resources/qml/hifi/commerce/Checkout.qml index 865bb72921..e33cf872cf 100644 --- a/interface/resources/qml/hifi/commerce/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/Checkout.qml @@ -68,6 +68,11 @@ Rectangle { } } + SecurityImageSelection { + id: securityImageSelection; + referrerURL: checkoutRoot.itemHref; + } + // // TITLE BAR START // diff --git a/interface/resources/qml/hifi/commerce/Inventory.qml b/interface/resources/qml/hifi/commerce/Inventory.qml index 7a5696e1d7..df4907e8b9 100644 --- a/interface/resources/qml/hifi/commerce/Inventory.qml +++ b/interface/resources/qml/hifi/commerce/Inventory.qml @@ -47,7 +47,6 @@ Rectangle { SecurityImageSelection { id: securityImageSelection; - visible: true; referrerURL: inventoryRoot.referrerURL; } diff --git a/interface/resources/qml/hifi/commerce/SecurityImageSelection.qml b/interface/resources/qml/hifi/commerce/SecurityImageSelection.qml index be6b15173e..33bb9edba2 100644 --- a/interface/resources/qml/hifi/commerce/SecurityImageSelection.qml +++ b/interface/resources/qml/hifi/commerce/SecurityImageSelection.qml @@ -32,8 +32,13 @@ Rectangle { Hifi.QmlCommerce { id: commerce; + onSecurityImageChosen: { + securityImageSelectionRoot.visible = (imageID == 0); + } } + visible: commerce.getSecurityImage() == 0; + // // TITLE BAR START // @@ -248,7 +253,7 @@ Rectangle { width: parent.width/2 - anchors.rightMargin*2; text: "Confirm"; onClicked: { - commerce.chooseSecurityImage(securityImageGrid.currentIndex); + commerce.chooseSecurityImage(securityImageGrid.currentIndex + 1); } } } diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp index 4eebb0fc39..d49ee8aaf3 100644 --- a/interface/src/commerce/QmlCommerce.cpp +++ b/interface/src/commerce/QmlCommerce.cpp @@ -49,9 +49,3 @@ void QmlCommerce::inventory() { auto wallet = DependencyManager::get(); ledger->inventory(wallet->listPublicKeys()); } - -void QmlCommerce::chooseSecurityImage(QmlCommerce::SecurityImage imageID) { - auto ledger = DependencyManager::get(); - auto wallet = DependencyManager::get(); - ledger->inventory(wallet->listPublicKeys()); -} \ No newline at end of file diff --git a/interface/src/commerce/QmlCommerce.h b/interface/src/commerce/QmlCommerce.h index 5653e4ec98..7422277631 100644 --- a/interface/src/commerce/QmlCommerce.h +++ b/interface/src/commerce/QmlCommerce.h @@ -30,6 +30,7 @@ signals: // 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(QJsonObject inventory, const QString& failureMessage); + void securityImageChosen(uint imageID); protected: Q_INVOKABLE void buy(const QString& assetId, int cost, const QString& buyerUsername = ""); @@ -38,10 +39,15 @@ protected: enum SecurityImage { NONE = 0, - Cat + Cat, + Car, + Dog, + Stars, + Plane, + Gingerbread }; - Q_INVOKABLE void chooseSecurityImage(SecurityImage imageID); - Q_INVOKABLE bool hasChosenSecurityImage() { return (QmlCommerce::_chosenSecurityImage != SecurityImage::NONE); } + Q_INVOKABLE void chooseSecurityImage(uint imageID) { QmlCommerce::_chosenSecurityImage = (SecurityImage)imageID; emit securityImageChosen(imageID); } + Q_INVOKABLE uint getSecurityImage() { return (uint)QmlCommerce::_chosenSecurityImage; } private: SecurityImage _chosenSecurityImage = SecurityImage::NONE; From b7282cc776880a2f0a531795306b705f3a4c0193 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 15 Aug 2017 13:46:20 -0700 Subject: [PATCH 43/56] Lots of fixes --- .../resources/qml/hifi/commerce/Inventory.qml | 19 +++++++ .../qml/hifi/commerce/SecurityImageModel.qml | 42 ++++++++++++++++ .../hifi/commerce/SecurityImageSelection.qml | 49 +++++++++---------- interface/src/commerce/QmlCommerce.cpp | 11 +++++ interface/src/commerce/QmlCommerce.h | 19 ++----- interface/src/commerce/Wallet.cpp | 10 +++- interface/src/commerce/Wallet.h | 20 ++++++++ scripts/system/marketplaces/marketplaces.js | 3 +- 8 files changed, 129 insertions(+), 44 deletions(-) create mode 100644 interface/resources/qml/hifi/commerce/SecurityImageModel.qml diff --git a/interface/resources/qml/hifi/commerce/Inventory.qml b/interface/resources/qml/hifi/commerce/Inventory.qml index df4907e8b9..a3e11e6426 100644 --- a/interface/resources/qml/hifi/commerce/Inventory.qml +++ b/interface/resources/qml/hifi/commerce/Inventory.qml @@ -78,6 +78,25 @@ Rectangle { verticalAlignment: Text.AlignVCenter; } + // "Change Security Image" button + HifiControlsUit.Button { + id: changeSecurityImageButton; + color: hifi.buttons.black; + colorScheme: hifi.colorSchemes.dark; + anchors.top: parent.top; + anchors.topMargin: 3; + anchors.bottom: parent.bottom; + anchors.bottomMargin: 3; + anchors.right: parent.right; + anchors.rightMargin: 20; + width: 200; + text: "Change Security Image" + onClicked: { + securityImageSelection.isManuallyChangingSecurityImage = true; + securityImageSelection.visible = true; + } + } + // Separator HifiControlsUit.Separator { anchors.left: parent.left; diff --git a/interface/resources/qml/hifi/commerce/SecurityImageModel.qml b/interface/resources/qml/hifi/commerce/SecurityImageModel.qml new file mode 100644 index 0000000000..df4490a5b1 --- /dev/null +++ b/interface/resources/qml/hifi/commerce/SecurityImageModel.qml @@ -0,0 +1,42 @@ +// +// SecurityImageModel.qml +// qml/hifi/commerce +// +// SecurityImageModel +// +// Created by Zach Fox on 2017-08-15 +// 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 + +ListModel { + id: root; + ListElement{ + sourcePath: "images/01cat.jpg" + securityImageEnumIndex: 1; + } + ListElement{ + sourcePath: "images/02car.jpg" + securityImageEnumIndex: 2; + } + ListElement{ + sourcePath: "images/03dog.jpg" + securityImageEnumIndex: 3; + } + ListElement{ + sourcePath: "images/04stars.jpg" + securityImageEnumIndex: 4; + } + ListElement{ + sourcePath: "images/05plane.jpg" + securityImageEnumIndex: 5; + } + ListElement{ + sourcePath: "images/06gingerbread.jpg" + securityImageEnumIndex: 6; + } +} diff --git a/interface/resources/qml/hifi/commerce/SecurityImageSelection.qml b/interface/resources/qml/hifi/commerce/SecurityImageSelection.qml index 33bb9edba2..744234c95a 100644 --- a/interface/resources/qml/hifi/commerce/SecurityImageSelection.qml +++ b/interface/resources/qml/hifi/commerce/SecurityImageSelection.qml @@ -25,19 +25,32 @@ Rectangle { id: securityImageSelectionRoot; property string referrerURL: ""; + property bool isManuallyChangingSecurityImage: false; anchors.fill: parent; // Style color: hifi.colors.baseGray; z:999; // On top of everything else + visible: false; Hifi.QmlCommerce { id: commerce; - onSecurityImageChosen: { - securityImageSelectionRoot.visible = (imageID == 0); + onSecurityImageResult: { + if (!isManuallyChangingSecurityImage) { + securityImageSelectionRoot.visible = (imageID == 0); + } + if (imageID !== 0) { + for (var itr = 0; itr < gridModel.count; itr++) { + if (gridModel.get(itr).securityImageEnumIndex === imageID) { + securityImageGrid.currentIndex = itr; + } + } + } } } - visible: commerce.getSecurityImage() == 0; + Component.onCompleted: { + commerce.getSecurityImage(); + } // // TITLE BAR START @@ -137,26 +150,8 @@ Rectangle { anchors.bottom: actionButtonsContainer.top; anchors.bottomMargin: 8; - ListModel { + SecurityImageModel { id: gridModel; - ListElement{ - sourcePath: "images/01cat.jpg" - } - ListElement{ - sourcePath: "images/02car.jpg" - } - ListElement{ - sourcePath: "images/03dog.jpg" - } - ListElement{ - sourcePath: "images/04stars.jpg" - } - ListElement{ - sourcePath: "images/05plane.jpg" - } - ListElement{ - sourcePath: "images/06gingerbread.jpg" - } } GridView { @@ -199,7 +194,6 @@ Rectangle { width: securityImageGrid.cellWidth; height: securityImageGrid.cellHeight; color: hifi.colors.blueHighlight; - y: securityImageGrid.currentItem.y; } } } @@ -235,7 +229,11 @@ Rectangle { width: parent.width/2 - anchors.leftMargin*2; text: "Cancel" onClicked: { - sendToScript({method: 'securityImageSelection_cancelClicked', referrerURL: referrerURL}); + if (!securityImageSelectionRoot.isManuallyChangingSecurityImage) { + sendToScript({method: 'securityImageSelection_cancelClicked', referrerURL: securityImageSelectionRoot.referrerURL}); + } else { + securityImageSelectionRoot.visible = false; + } } } @@ -253,7 +251,8 @@ Rectangle { width: parent.width/2 - anchors.rightMargin*2; text: "Confirm"; onClicked: { - commerce.chooseSecurityImage(securityImageGrid.currentIndex + 1); + securityImageSelectionRoot.isManuallyChangingSecurityImage = false; + commerce.chooseSecurityImage(gridModel.get(securityImageGrid.currentIndex).securityImageEnumIndex); } } } diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp index d49ee8aaf3..573740727f 100644 --- a/interface/src/commerce/QmlCommerce.cpp +++ b/interface/src/commerce/QmlCommerce.cpp @@ -19,9 +19,11 @@ HIFI_QML_DEF(QmlCommerce) QmlCommerce::QmlCommerce(QQuickItem* parent) : OffscreenQmlDialog(parent) { auto ledger = DependencyManager::get(); + auto wallet = DependencyManager::get(); connect(ledger.data(), &Ledger::buyResult, this, &QmlCommerce::buyResult); connect(ledger.data(), &Ledger::balanceResult, this, &QmlCommerce::balanceResult); connect(ledger.data(), &Ledger::inventoryResult, this, &QmlCommerce::inventoryResult); + connect(wallet.data(), &Wallet::securityImageResult, this, &QmlCommerce::securityImageResult); } void QmlCommerce::buy(const QString& assetId, int cost, const QString& buyerUsername) { @@ -49,3 +51,12 @@ void QmlCommerce::inventory() { auto wallet = DependencyManager::get(); ledger->inventory(wallet->listPublicKeys()); } + +void QmlCommerce::chooseSecurityImage(uint imageID) { + auto wallet = DependencyManager::get(); + wallet->chooseSecurityImage(imageID); +} +void QmlCommerce::getSecurityImage() { + auto wallet = DependencyManager::get(); + wallet->getSecurityImage(); +} \ No newline at end of file diff --git a/interface/src/commerce/QmlCommerce.h b/interface/src/commerce/QmlCommerce.h index 7422277631..5b702bfeff 100644 --- a/interface/src/commerce/QmlCommerce.h +++ b/interface/src/commerce/QmlCommerce.h @@ -30,27 +30,14 @@ signals: // 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(QJsonObject inventory, const QString& failureMessage); - void securityImageChosen(uint imageID); + void securityImageResult(uint imageID); protected: Q_INVOKABLE void buy(const QString& assetId, int cost, const QString& buyerUsername = ""); Q_INVOKABLE void balance(); Q_INVOKABLE void inventory(); - - enum SecurityImage { - NONE = 0, - Cat, - Car, - Dog, - Stars, - Plane, - Gingerbread - }; - Q_INVOKABLE void chooseSecurityImage(uint imageID) { QmlCommerce::_chosenSecurityImage = (SecurityImage)imageID; emit securityImageChosen(imageID); } - Q_INVOKABLE uint getSecurityImage() { return (uint)QmlCommerce::_chosenSecurityImage; } - -private: - SecurityImage _chosenSecurityImage = SecurityImage::NONE; + Q_INVOKABLE void chooseSecurityImage(uint imageID); + Q_INVOKABLE void getSecurityImage(); }; #endif // hifi_QmlCommerce_h diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index 34d89b54b0..9edbeddd6e 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -43,4 +43,12 @@ QStringList Wallet::listPublicKeys() { QString Wallet::signWithKey(const QString& text, const QString& key) { qCInfo(commerce) << "Signing text."; return "fixme signed"; -} \ No newline at end of file +} + +void Wallet::chooseSecurityImage(uint imageID) { + _chosenSecurityImage = (SecurityImage)imageID; + emit securityImageResult(imageID); +} +void Wallet::getSecurityImage() { + emit securityImageResult(_chosenSecurityImage); +} diff --git a/interface/src/commerce/Wallet.h b/interface/src/commerce/Wallet.h index 79de5e81da..86638b5c75 100644 --- a/interface/src/commerce/Wallet.h +++ b/interface/src/commerce/Wallet.h @@ -26,9 +26,29 @@ public: bool generateKeyPair(); QStringList listPublicKeys(); QString signWithKey(const QString& text, const QString& key); + void chooseSecurityImage(uint imageID); + void getSecurityImage(); + +signals: + void securityImageResult(uint imageID); + +protected: + // ALWAYS add SecurityImage enum values to the END of the enum. + // They must be in the same order as the images are listed in + // SecurityImageSelection.qml + enum SecurityImage { + NONE = 0, + Cat, + Car, + Dog, + Stars, + Plane, + Gingerbread + }; private: QStringList _publicKeys{}; + SecurityImage _chosenSecurityImage = SecurityImage::NONE; }; #endif // hifi_Wallet_h diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index 3e86063dd6..84d7d44689 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -88,7 +88,7 @@ function onScreenChanged(type, url) { onMarketplaceScreen = type === "Web" && url === MARKETPLACE_URL_INITIAL; - wireEventBridge(type === "QML" && (url === MARKETPLACE_CHECKOUT_QML_PATH || url === MARKETPLACE_INVENTORY_QML_PATH)); + wireEventBridge(type === "QML" && (url === MARKETPLACE_CHECKOUT_QML_PATH || url === MARKETPLACE_INVENTORY_QML_PATH || url === MARKETPLACE_SECURITY_QML_PATH)); // for toolbar mode: change button to active when window is first openend, false otherwise. marketplaceButton.editProperties({ isActive: onMarketplaceScreen }); if (type === "Web" && url.indexOf(MARKETPLACE_URL) !== -1) { @@ -219,7 +219,6 @@ tablet.gotoWebScreen(message.referrerURL, MARKETPLACES_INJECT_SCRIPT_URL); break; case 'securityImageSelection_cancelClicked': - console.log("ZRF HERE " + message.referrerURL); tablet.gotoWebScreen(message.referrerURL, MARKETPLACES_INJECT_SCRIPT_URL); break; default: From f46198c2fdc7bb006fab3a35fc22f57be31fe2a6 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 15 Aug 2017 13:44:03 -0700 Subject: [PATCH 44/56] Simplified/Improved avatar capsule calculation IK is no longer performed during capsule calculation, This fixes an issue with the mannequin avatar in the marketplace. Specifically, it was causing the hips to rise during IK which would result in an incorrectly sized and offset capsule. --- libraries/animation/src/Rig.cpp | 61 ++++----------------------------- 1 file changed, 6 insertions(+), 55 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 3a31ccd25f..2eab4f9996 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1761,59 +1761,11 @@ void Rig::computeAvatarBoundingCapsule( return; } - AnimInverseKinematics ikNode("boundingShape"); - ikNode.setSkeleton(_animSkeleton); - - ikNode.setTargetVars("LeftHand", "leftHandPosition", "leftHandRotation", - "leftHandType", "leftHandWeight", 1.0f, {}, - QString(), QString(), QString()); - ikNode.setTargetVars("RightHand", "rightHandPosition", "rightHandRotation", - "rightHandType", "rightHandWeight", 1.0f, {}, - QString(), QString(), QString()); - ikNode.setTargetVars("LeftFoot", "leftFootPosition", "leftFootRotation", - "leftFootType", "leftFootWeight", 1.0f, {}, - QString(), QString(), QString()); - ikNode.setTargetVars("RightFoot", "rightFootPosition", "rightFootRotation", - "rightFootType", "rightFootWeight", 1.0f, {}, - QString(), QString(), QString()); glm::vec3 hipsPosition(0.0f); int hipsIndex = indexOfJoint("Hips"); if (hipsIndex >= 0) { hipsPosition = transformPoint(_geometryToRigTransform, _animSkeleton->getAbsoluteDefaultPose(hipsIndex).trans()); } - AnimVariantMap animVars; - animVars.setRigToGeometryTransform(_rigToGeometryTransform); - glm::quat handRotation = glm::angleAxis(PI, Vectors::UNIT_X); - animVars.set("leftHandPosition", hipsPosition); - animVars.set("leftHandRotation", handRotation); - animVars.set("leftHandType", (int)IKTarget::Type::RotationAndPosition); - animVars.set("rightHandPosition", hipsPosition); - animVars.set("rightHandRotation", handRotation); - animVars.set("rightHandType", (int)IKTarget::Type::RotationAndPosition); - - int rightFootIndex = indexOfJoint("RightFoot"); - int leftFootIndex = indexOfJoint("LeftFoot"); - if (rightFootIndex != -1 && leftFootIndex != -1) { - glm::vec3 geomFootPosition = glm::vec3(0.0f, _animSkeleton->getAbsoluteDefaultPose(rightFootIndex).trans().y, 0.0f); - glm::vec3 footPosition = transformPoint(_geometryToRigTransform, geomFootPosition); - glm::quat footRotation = glm::angleAxis(0.5f * PI, Vectors::UNIT_X); - animVars.set("leftFootPosition", footPosition); - animVars.set("leftFootRotation", footRotation); - animVars.set("leftFootType", (int)IKTarget::Type::RotationAndPosition); - animVars.set("rightFootPosition", footPosition); - animVars.set("rightFootRotation", footRotation); - animVars.set("rightFootType", (int)IKTarget::Type::RotationAndPosition); - } - - // call overlay twice: once to verify AnimPoseVec joints and again to do the IK - AnimNode::Triggers triggersOut; - AnimContext context(false, false, false, _geometryToRigTransform, _rigToGeometryTransform); - float dt = 1.0f; // the value of this does not matter - ikNode.overlay(animVars, context, dt, triggersOut, _animSkeleton->getRelativeBindPoses()); - AnimPoseVec finalPoses = ikNode.overlay(animVars, context, dt, triggersOut, _animSkeleton->getRelativeBindPoses()); - - // convert relative poses to absolute - _animSkeleton->convertRelativePosesToAbsolute(finalPoses); // compute bounding box that encloses all points Extents totalExtents; @@ -1824,15 +1776,15 @@ void Rig::computeAvatarBoundingCapsule( // even if they do not have legs (default robot) totalExtents.addPoint(glm::vec3(0.0f)); - // HACK to reduce the radius of the bounding capsule to be tight with the torso, we only consider joints + // To reduce the radius of the bounding capsule to be tight with the torso, we only consider joints // from the head to the hips when computing the rest of the bounding capsule. int index = indexOfJoint("Head"); while (index != -1) { const FBXJointShapeInfo& shapeInfo = geometry.joints.at(index).shapeInfo; - AnimPose pose = finalPoses[index]; + AnimPose pose = _animSkeleton->getAbsoluteDefaultPose(index); if (shapeInfo.points.size() > 0) { - for (size_t j = 0; j < shapeInfo.points.size(); ++j) { - totalExtents.addPoint((pose * shapeInfo.points[j])); + for (auto& point : shapeInfo.points) { + totalExtents.addPoint((pose * point)); } } index = _animSkeleton->getParentIndex(index); @@ -1846,7 +1798,6 @@ void Rig::computeAvatarBoundingCapsule( radiusOut = 0.5f * sqrtf(0.5f * (diagonal.x * diagonal.x + diagonal.z * diagonal.z)); heightOut = diagonal.y - 2.0f * radiusOut; - glm::vec3 rootPosition = finalPoses[geometry.rootJointIndex].trans(); - glm::vec3 rigCenter = transformPoint(_geometryToRigTransform, (0.5f * (totalExtents.maximum + totalExtents.minimum))); - localOffsetOut = rigCenter - transformPoint(_geometryToRigTransform, rootPosition); + glm::vec3 capsuleCenter = transformPoint(_geometryToRigTransform, (0.5f * (totalExtents.maximum + totalExtents.minimum))); + localOffsetOut = capsuleCenter - hipsPosition; } From c0fa446b75de60f5d51d6ab3a07e6bd692495f6f Mon Sep 17 00:00:00 2001 From: Liv Date: Tue, 15 Aug 2017 13:49:13 -0700 Subject: [PATCH 45/56] 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 46/56] 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 768eb7f91ced1b1e9081b1606ec48e54770c18f8 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 15 Aug 2017 15:02:28 -0700 Subject: [PATCH 47/56] Getting closer --- .../resources/qml/hifi/commerce/Inventory.qml | 28 +++++++++++++++++-- .../qml/hifi/commerce/SecurityImageModel.qml | 12 ++++---- .../hifi/commerce/SecurityImageSelection.qml | 8 ++++-- 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/Inventory.qml b/interface/resources/qml/hifi/commerce/Inventory.qml index a3e11e6426..17024be0a3 100644 --- a/interface/resources/qml/hifi/commerce/Inventory.qml +++ b/interface/resources/qml/hifi/commerce/Inventory.qml @@ -43,12 +43,18 @@ Rectangle { inventoryContentsList.model = inventory.assets; } } + onSecurityImageResult: { + securityImage.source = imageID ? gridModel.get(imageID - 1).sourcePath : ""; + } } SecurityImageSelection { id: securityImageSelection; referrerURL: inventoryRoot.referrerURL; } + SecurityImageModel { + id: gridModel; + } // // TITLE BAR START @@ -56,7 +62,7 @@ Rectangle { Item { id: titleBarContainer; // Size - width: inventoryRoot.width; + width: parent.width; height: 50; // Anchors anchors.left: parent.left; @@ -69,8 +75,11 @@ Rectangle { // Text size size: hifi.fontSizes.overlayTitle; // Anchors - anchors.fill: parent; + anchors.top: parent.top; + anchors.left: parent.left; anchors.leftMargin: 16; + anchors.bottom: parent.bottom; + width: paintedWidth; // Style color: hifi.colors.lightGrayText; // Alignment @@ -78,6 +87,20 @@ Rectangle { verticalAlignment: Text.AlignVCenter; } + // Security Image + Image { + id: securityImage; + // Anchors + anchors.top: parent.top; + anchors.left: titleBarText.right; + anchors.leftMargin: 16; + height: parent.height - 5; + width: height; + anchors.horizontalCenter: parent.horizontalCenter; + anchors.verticalCenter: parent.verticalCenter; + fillMode: Image.PreserveAspectFit; + } + // "Change Security Image" button HifiControlsUit.Button { id: changeSecurityImageButton; @@ -286,6 +309,7 @@ Rectangle { referrerURL = message.referrerURL; commerce.balance(); commerce.inventory(); + commerce.getSecurityImage(); break; default: console.log('Unrecognized message from marketplaces.js:', JSON.stringify(message)); diff --git a/interface/resources/qml/hifi/commerce/SecurityImageModel.qml b/interface/resources/qml/hifi/commerce/SecurityImageModel.qml index df4490a5b1..2fbf28683f 100644 --- a/interface/resources/qml/hifi/commerce/SecurityImageModel.qml +++ b/interface/resources/qml/hifi/commerce/SecurityImageModel.qml @@ -17,26 +17,26 @@ ListModel { id: root; ListElement{ sourcePath: "images/01cat.jpg" - securityImageEnumIndex: 1; + securityImageEnumValue: 1; } ListElement{ sourcePath: "images/02car.jpg" - securityImageEnumIndex: 2; + securityImageEnumValue: 2; } ListElement{ sourcePath: "images/03dog.jpg" - securityImageEnumIndex: 3; + securityImageEnumValue: 3; } ListElement{ sourcePath: "images/04stars.jpg" - securityImageEnumIndex: 4; + securityImageEnumValue: 4; } ListElement{ sourcePath: "images/05plane.jpg" - securityImageEnumIndex: 5; + securityImageEnumValue: 5; } ListElement{ sourcePath: "images/06gingerbread.jpg" - securityImageEnumIndex: 6; + securityImageEnumValue: 6; } } diff --git a/interface/resources/qml/hifi/commerce/SecurityImageSelection.qml b/interface/resources/qml/hifi/commerce/SecurityImageSelection.qml index 744234c95a..70e9baaf40 100644 --- a/interface/resources/qml/hifi/commerce/SecurityImageSelection.qml +++ b/interface/resources/qml/hifi/commerce/SecurityImageSelection.qml @@ -26,6 +26,7 @@ Rectangle { id: securityImageSelectionRoot; property string referrerURL: ""; property bool isManuallyChangingSecurityImage: false; + property int imageEnumValue: 0; anchors.fill: parent; // Style color: hifi.colors.baseGray; @@ -40,8 +41,11 @@ Rectangle { } if (imageID !== 0) { for (var itr = 0; itr < gridModel.count; itr++) { - if (gridModel.get(itr).securityImageEnumIndex === imageID) { + var thisValue = gridModel.get(itr).securityImageEnumValue; + if (thisValue === imageID) { + securityImageSelectionRoot.imageEnumValue = thisValue; securityImageGrid.currentIndex = itr; + return; } } } @@ -252,7 +256,7 @@ Rectangle { text: "Confirm"; onClicked: { securityImageSelectionRoot.isManuallyChangingSecurityImage = false; - commerce.chooseSecurityImage(gridModel.get(securityImageGrid.currentIndex).securityImageEnumIndex); + commerce.chooseSecurityImage(gridModel.get(securityImageGrid.currentIndex).securityImageEnumValue); } } } From 1ae4a5c01901120e6b653a358c2954ffe688f0f3 Mon Sep 17 00:00:00 2001 From: Liv Date: Tue, 15 Aug 2017 15:30:43 -0700 Subject: [PATCH 48/56] 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"; } From 29a9ae28e99119e2d62461785cba3e9a14961c66 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 15 Aug 2017 15:36:28 -0700 Subject: [PATCH 49/56] Fixes --- .../resources/qml/hifi/commerce/Inventory.qml | 5 +---- .../hifi/commerce/SecurityImageSelection.qml | 17 ++++++----------- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/Inventory.qml b/interface/resources/qml/hifi/commerce/Inventory.qml index 17024be0a3..ca01fbec7b 100644 --- a/interface/resources/qml/hifi/commerce/Inventory.qml +++ b/interface/resources/qml/hifi/commerce/Inventory.qml @@ -44,7 +44,7 @@ Rectangle { } } onSecurityImageResult: { - securityImage.source = imageID ? gridModel.get(imageID - 1).sourcePath : ""; + securityImage.source = securityImageSelection.getImagePathFromImageID(imageID); } } @@ -52,9 +52,6 @@ Rectangle { id: securityImageSelection; referrerURL: inventoryRoot.referrerURL; } - SecurityImageModel { - id: gridModel; - } // // TITLE BAR START diff --git a/interface/resources/qml/hifi/commerce/SecurityImageSelection.qml b/interface/resources/qml/hifi/commerce/SecurityImageSelection.qml index 70e9baaf40..73698dbd45 100644 --- a/interface/resources/qml/hifi/commerce/SecurityImageSelection.qml +++ b/interface/resources/qml/hifi/commerce/SecurityImageSelection.qml @@ -26,7 +26,6 @@ Rectangle { id: securityImageSelectionRoot; property string referrerURL: ""; property bool isManuallyChangingSecurityImage: false; - property int imageEnumValue: 0; anchors.fill: parent; // Style color: hifi.colors.baseGray; @@ -39,13 +38,12 @@ Rectangle { if (!isManuallyChangingSecurityImage) { securityImageSelectionRoot.visible = (imageID == 0); } - if (imageID !== 0) { + if (imageID > 0) { for (var itr = 0; itr < gridModel.count; itr++) { var thisValue = gridModel.get(itr).securityImageEnumValue; if (thisValue === imageID) { - securityImageSelectionRoot.imageEnumValue = thisValue; securityImageGrid.currentIndex = itr; - return; + break; } } } @@ -182,16 +180,9 @@ Rectangle { } MouseArea { anchors.fill: parent; - hoverEnabled: enabled; onClicked: { securityImageGrid.currentIndex = index; } - onEntered: { - //thisItemId.color = hifi.colors.blueHighlight; - } - onExited: { - //thisItemId.color = hifi.colors.blueAccent; - } } } highlight: Rectangle { @@ -268,6 +259,10 @@ Rectangle { // FUNCTION DEFINITIONS START // signal sendToScript(var message); + + function getImagePathFromImageID(imageID) { + return (imageID ? gridModel.get(imageID - 1).sourcePath : ""); + } // // FUNCTION DEFINITIONS END // From ccf2d71036af65e4c2194de3cf59025eb03f625d Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 15 Aug 2017 15:42:53 -0700 Subject: [PATCH 50/56] V1 done --- .../resources/qml/hifi/commerce/Checkout.qml | 22 ++++++++++++++++++- .../resources/qml/hifi/commerce/Inventory.qml | 1 - .../hifi/commerce/SecurityImageSelection.qml | 4 ++-- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/Checkout.qml b/interface/resources/qml/hifi/commerce/Checkout.qml index e33cf872cf..2b0cae78bb 100644 --- a/interface/resources/qml/hifi/commerce/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/Checkout.qml @@ -66,6 +66,9 @@ Rectangle { } } } + onSecurityImageResult: { + securityImage.source = securityImageSelection.getImagePathFromImageID(imageID); + } } SecurityImageSelection { @@ -92,8 +95,11 @@ Rectangle { // Text size size: hifi.fontSizes.overlayTitle; // Anchors - anchors.fill: parent; + anchors.top: parent.top; + anchors.left: parent.left; anchors.leftMargin: 16; + anchors.bottom: parent.bottom; + width: paintedWidth; // Style color: hifi.colors.lightGrayText; // Alignment @@ -101,6 +107,19 @@ Rectangle { verticalAlignment: Text.AlignVCenter; } + // Security Image + Image { + id: securityImage; + // Anchors + anchors.top: parent.top; + anchors.left: titleBarText.right; + anchors.leftMargin: 16; + height: parent.height - 5; + width: height; + anchors.verticalCenter: parent.verticalCenter; + fillMode: Image.PreserveAspectFit; + } + // Separator HifiControlsUit.Separator { anchors.left: parent.left; @@ -432,6 +451,7 @@ Rectangle { itemHref = message.params.itemHref; commerce.balance(); commerce.inventory(); + commerce.getSecurityImage(); break; default: console.log('Unrecognized message from marketplaces.js:', JSON.stringify(message)); diff --git a/interface/resources/qml/hifi/commerce/Inventory.qml b/interface/resources/qml/hifi/commerce/Inventory.qml index ca01fbec7b..5eb2b7865e 100644 --- a/interface/resources/qml/hifi/commerce/Inventory.qml +++ b/interface/resources/qml/hifi/commerce/Inventory.qml @@ -93,7 +93,6 @@ Rectangle { anchors.leftMargin: 16; height: parent.height - 5; width: height; - anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: parent.verticalCenter; fillMode: Image.PreserveAspectFit; } diff --git a/interface/resources/qml/hifi/commerce/SecurityImageSelection.qml b/interface/resources/qml/hifi/commerce/SecurityImageSelection.qml index 73698dbd45..c030f642b8 100644 --- a/interface/resources/qml/hifi/commerce/SecurityImageSelection.qml +++ b/interface/resources/qml/hifi/commerce/SecurityImageSelection.qml @@ -161,8 +161,8 @@ Rectangle { // Anchors anchors.fill: parent; currentIndex: -1; - cellWidth: width/2; - cellHeight: height/3; + cellWidth: width / 2; + cellHeight: height / 3; model: gridModel; delegate: Item { width: securityImageGrid.cellWidth; From 5c157a73975a1737561622346beaf52333e3f77b Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 15 Aug 2017 16:24:14 -0700 Subject: [PATCH 51/56] Move security image to top left --- .../resources/qml/hifi/commerce/Checkout.qml | 28 +++++++++---------- .../resources/qml/hifi/commerce/Inventory.qml | 28 +++++++++---------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/Checkout.qml b/interface/resources/qml/hifi/commerce/Checkout.qml index 2b0cae78bb..c7b5b080d0 100644 --- a/interface/resources/qml/hifi/commerce/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/Checkout.qml @@ -88,6 +88,19 @@ Rectangle { anchors.left: parent.left; anchors.top: parent.top; + // Security Image + Image { + id: securityImage; + // Anchors + anchors.top: parent.top; + anchors.left: parent.left; + anchors.leftMargin: 16; + height: parent.height - 5; + width: height; + anchors.verticalCenter: parent.verticalCenter; + fillMode: Image.PreserveAspectFit; + } + // Title Bar text RalewaySemiBold { id: titleBarText; @@ -96,7 +109,7 @@ Rectangle { size: hifi.fontSizes.overlayTitle; // Anchors anchors.top: parent.top; - anchors.left: parent.left; + anchors.left: securityImage.right; anchors.leftMargin: 16; anchors.bottom: parent.bottom; width: paintedWidth; @@ -107,19 +120,6 @@ Rectangle { verticalAlignment: Text.AlignVCenter; } - // Security Image - Image { - id: securityImage; - // Anchors - anchors.top: parent.top; - anchors.left: titleBarText.right; - anchors.leftMargin: 16; - height: parent.height - 5; - width: height; - anchors.verticalCenter: parent.verticalCenter; - fillMode: Image.PreserveAspectFit; - } - // Separator HifiControlsUit.Separator { anchors.left: parent.left; diff --git a/interface/resources/qml/hifi/commerce/Inventory.qml b/interface/resources/qml/hifi/commerce/Inventory.qml index 5eb2b7865e..488efb3872 100644 --- a/interface/resources/qml/hifi/commerce/Inventory.qml +++ b/interface/resources/qml/hifi/commerce/Inventory.qml @@ -65,6 +65,19 @@ Rectangle { anchors.left: parent.left; anchors.top: parent.top; + // Security Image + Image { + id: securityImage; + // Anchors + anchors.top: parent.top; + anchors.left: parent.left; + anchors.leftMargin: 16; + height: parent.height - 5; + width: height; + anchors.verticalCenter: parent.verticalCenter; + fillMode: Image.PreserveAspectFit; + } + // Title Bar text RalewaySemiBold { id: titleBarText; @@ -73,7 +86,7 @@ Rectangle { size: hifi.fontSizes.overlayTitle; // Anchors anchors.top: parent.top; - anchors.left: parent.left; + anchors.left: securityImage.right; anchors.leftMargin: 16; anchors.bottom: parent.bottom; width: paintedWidth; @@ -84,19 +97,6 @@ Rectangle { verticalAlignment: Text.AlignVCenter; } - // Security Image - Image { - id: securityImage; - // Anchors - anchors.top: parent.top; - anchors.left: titleBarText.right; - anchors.leftMargin: 16; - height: parent.height - 5; - width: height; - anchors.verticalCenter: parent.verticalCenter; - fillMode: Image.PreserveAspectFit; - } - // "Change Security Image" button HifiControlsUit.Button { id: changeSecurityImageButton; From 984a5aea2c00c15776e80070a3bfa5724d66d5ee Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 15 Aug 2017 16:32:23 -0700 Subject: [PATCH 52/56] You can now spawn infinite copies of items you've previously purchased --- interface/resources/qml/hifi/commerce/Checkout.qml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/Checkout.qml b/interface/resources/qml/hifi/commerce/Checkout.qml index c7b5b080d0..435aea83fb 100644 --- a/interface/resources/qml/hifi/commerce/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/Checkout.qml @@ -405,7 +405,7 @@ Rectangle { // "Buy" button HifiControlsUit.Button { id: buyButton; - enabled: balanceAfterPurchase >= 0 && !alreadyOwned && inventoryReceived && balanceReceived; + enabled: balanceAfterPurchase >= 0 && inventoryReceived && balanceReceived; color: hifi.buttons.black; colorScheme: hifi.colorSchemes.dark; anchors.top: parent.top; @@ -415,9 +415,16 @@ Rectangle { anchors.right: parent.right; anchors.rightMargin: 20; width: parent.width/2 - anchors.rightMargin*2; - text: (inventoryReceived && balanceReceived) ? (alreadyOwned ? "Already Owned" : "Buy") : "--"; + text: (inventoryReceived && balanceReceived) ? (alreadyOwned ? "Already Owned: Get Item" : "Buy") : "--"; onClicked: { - commerce.buy(itemId, parseInt(itemPriceText.text)); + if (!alreadyOwned) { + commerce.buy(itemId, parseInt(itemPriceText.text)); + } else { + if (urlHandler.canHandleUrl(itemHref)) { + urlHandler.handleUrl(itemHref); + } + sendToScript({method: 'checkout_buySuccess', itemId: itemId}); + } } } } From 2fa1bd25a8f563d85296e96e3df73dfb99d043f3 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 15 Aug 2017 16:41:04 -0700 Subject: [PATCH 53/56] Clipping and mipping! --- interface/resources/qml/hifi/commerce/Checkout.qml | 1 + interface/resources/qml/hifi/commerce/Inventory.qml | 2 ++ .../resources/qml/hifi/commerce/SecurityImageSelection.qml | 6 ++++-- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/Checkout.qml b/interface/resources/qml/hifi/commerce/Checkout.qml index 435aea83fb..b9d15b61e4 100644 --- a/interface/resources/qml/hifi/commerce/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/Checkout.qml @@ -99,6 +99,7 @@ Rectangle { width: height; anchors.verticalCenter: parent.verticalCenter; fillMode: Image.PreserveAspectFit; + mipmap: true; } // Title Bar text diff --git a/interface/resources/qml/hifi/commerce/Inventory.qml b/interface/resources/qml/hifi/commerce/Inventory.qml index 488efb3872..d7ffae7c3c 100644 --- a/interface/resources/qml/hifi/commerce/Inventory.qml +++ b/interface/resources/qml/hifi/commerce/Inventory.qml @@ -76,6 +76,7 @@ Rectangle { width: height; anchors.verticalCenter: parent.verticalCenter; fillMode: Image.PreserveAspectFit; + mipmap: true; } // Title Bar text @@ -209,6 +210,7 @@ Rectangle { } ListView { id: inventoryContentsList; + clip: true; // Anchors anchors.top: inventoryContentsLabel.bottom; anchors.topMargin: 8; diff --git a/interface/resources/qml/hifi/commerce/SecurityImageSelection.qml b/interface/resources/qml/hifi/commerce/SecurityImageSelection.qml index c030f642b8..7775f1ff9c 100644 --- a/interface/resources/qml/hifi/commerce/SecurityImageSelection.qml +++ b/interface/resources/qml/hifi/commerce/SecurityImageSelection.qml @@ -158,6 +158,7 @@ Rectangle { GridView { id: securityImageGrid; + clip: true; // Anchors anchors.fill: parent; currentIndex: -1; @@ -170,12 +171,13 @@ Rectangle { Item { anchors.fill: parent; Image { - width: parent.width - 20; - height: parent.height - 20; + width: parent.width - 8; + height: parent.height - 8; source: sourcePath; anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: parent.verticalCenter; fillMode: Image.PreserveAspectFit; + mipmap: true; } } MouseArea { From e9b8e5431d2bebc74995f1a17209fece32a9bac5 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 15 Aug 2017 17:26:51 -0700 Subject: [PATCH 54/56] Fix for incorrectly scaled bounding volumes when switching avatars Make sure to explicitly set the _geometryToRigTransform in Rig::initJointStates(). This should fix small bounding volume when switching from the Gamebot avatar (which has 0.008 scaling) to another avatar (which ususally have 0.01 scaling). --- libraries/animation/src/Rig.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 2eab4f9996..1b91737364 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -168,6 +168,8 @@ void Rig::destroyAnimGraph() { void Rig::initJointStates(const FBXGeometry& geometry, const glm::mat4& modelOffset) { _geometryOffset = AnimPose(geometry.offset); _invGeometryOffset = _geometryOffset.inverse(); + _geometryToRigTransform = modelOffset * geometry.offset; + _rigToGeometryTransform = glm::inverse(_geometryToRigTransform); setModelOffset(modelOffset); _animSkeleton = std::make_shared(geometry); From cc2ff565ac549de78a7fe43b5ac07b46e267b023 Mon Sep 17 00:00:00 2001 From: LaShonda Hopper <1p-cusack@1stplayable.com> Date: Wed, 2 Aug 2017 14:55:10 -0400 Subject: [PATCH 55/56] [Case 6491] Ran lint on entitySelectionTool.js (details below). Prior Issue Count: 35 Current Issue Count: 3 Resolved: * 17 used out of scope issues. * 11 already defined issues. * 2 missing semicolon issues. * 1 implicit comparison against null issue. * 1 readability warning. Remaining Issues as of this commit: * scripts/system/libraries/entitySelectionTool.js: line 17, col 1, Read only. ** HIFI_PUBLIC_BUCKET assignment * scripts/system/libraries/entitySelectionTool.js: line 19, col 1, Read only. ** SPACE_WORLD assignment * scripts/system/libraries/entitySelectionTool.js: line 30, col 1, Read only. ** SelectionManager assignment One notable item was a chunk of code from makeStretchTool's onMove function which wasn't in scope of the vars being utilized. Changes Committed: modified: scripts/system/libraries/entitySelectionTool.js --- .../system/libraries/entitySelectionTool.js | 148 ++++++++++-------- 1 file changed, 81 insertions(+), 67 deletions(-) diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index 30d54e3530..44f3c9e041 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -30,11 +30,13 @@ function objectTranslationPlanePoint(position, dimensions) { SelectionManager = (function() { var that = {}; + // FUNCTION: SUBSCRIBE TO UPDATE MESSAGES function subscribeToUpdateMessages() { Messages.subscribe("entityToolUpdates"); Messages.messageReceived.connect(handleEntitySelectionToolUpdates); } + // FUNCTION: HANDLE ENTITY SELECTION TOOL UDPATES function handleEntitySelectionToolUpdates(channel, message, sender) { if (channel !== 'entityToolUpdates') { return; @@ -238,6 +240,7 @@ function normalizeDegrees(degrees) { return degrees; } +// FUNCTION: getRelativeCenterPosition // Return the enter position of an entity relative to it's registrationPoint // A registration point of (0.5, 0.5, 0.5) will have an offset of (0, 0, 0) // A registration point of (1.0, 1.0, 1.0) will have an offset of (-dimensions.x / 2, -dimensions.y / 2, -dimensions.z / 2) @@ -249,6 +252,7 @@ function getRelativeCenterPosition(dimensions, registrationPoint) { }; } +// SELECTION DISPLAY DEFINITION SelectionDisplay = (function() { var that = {}; @@ -1152,6 +1156,7 @@ SelectionDisplay = (function() { that.updateHandles(); }; + // FUNCTION: UPDATE ROTATION HANDLES that.updateRotationHandles = function() { var diagonal = (Vec3.length(selectionManager.worldDimensions) / 2) * 1.1; var halfDimensions = Vec3.multiply(selectionManager.worldDimensions, 0.5); @@ -1545,11 +1550,6 @@ SelectionDisplay = (function() { translateHandlesVisible = false; } - var rotation = selectionManager.worldRotation; - var dimensions = selectionManager.worldDimensions; - var position = selectionManager.worldPosition; - - Overlays.editOverlay(rotateOverlayTarget, { visible: rotationOverlaysVisible }); @@ -1577,6 +1577,7 @@ SelectionDisplay = (function() { }); }; + // FUNCTION: SET SPACE MODE that.setSpaceMode = function(newSpaceMode) { if (spaceMode != newSpaceMode) { spaceMode = newSpaceMode; @@ -1584,6 +1585,7 @@ SelectionDisplay = (function() { } }; + // FUNCTION: TOGGLE SPACE MODE that.toggleSpaceMode = function() { if (spaceMode == SPACE_WORLD && SelectionManager.selections.length > 1) { print("Local space editing is not available with multiple selections"); @@ -1593,8 +1595,11 @@ SelectionDisplay = (function() { that.updateHandles(); }; + // FUNCTION: UNSELECT ALL + // TODO?: Needs implementation that.unselectAll = function() {}; + // FUNCTION: UPDATE HANDLES that.updateHandles = function() { if (SelectionManager.selections.length === 0) { that.setOverlaysVisible(false); @@ -2168,10 +2173,10 @@ SelectionDisplay = (function() { position: EdgeTR }); - var boxPosition = Vec3.multiplyQbyV(rotation, center); - boxPosition = Vec3.sum(position, boxPosition); + var selectionBoxPosition = Vec3.multiplyQbyV(rotation, center); + selectionBoxPosition = Vec3.sum(position, selectionBoxPosition); Overlays.editOverlay(selectionBox, { - position: boxPosition, + position: selectionBoxPosition, dimensions: dimensions, rotation: rotation, visible: !(mode == "ROTATE_YAW" || mode == "ROTATE_PITCH" || mode == "ROTATE_ROLL"), @@ -2218,13 +2223,13 @@ SelectionDisplay = (function() { var offset = vec3Mult(props.dimensions, centeredRP); offset = Vec3.multiply(-1, offset); offset = Vec3.multiplyQbyV(props.rotation, offset); - var boxPosition = Vec3.sum(props.position, offset); + var curBoxPosition = Vec3.sum(props.position, offset); var color = {red: 255, green: 128, blue: 0}; if (i >= selectionManager.selections.length - 1) color = {red: 255, green: 255, blue: 64}; Overlays.editOverlay(selectionBoxes[i], { - position: boxPosition, + position: curBoxPosition, color: color, rotation: props.rotation, dimensions: props.dimensions, @@ -2305,9 +2310,9 @@ SelectionDisplay = (function() { x: position.x, y: position.y + worldTop + grabberMoveUpOffset, z: position.z - } + }; Overlays.editOverlay(grabberMoveUp, { - visible: activeTool == null || mode == "TRANSLATE_UP_DOWN" + visible: (activeTool === null) || (mode == "TRANSLATE_UP_DOWN") }); Overlays.editOverlay(baseOfEntityProjectionOverlay, { @@ -2327,21 +2332,24 @@ SelectionDisplay = (function() { }; + // FUNCTION: SET OVERLAYS VISIBLE that.setOverlaysVisible = function(isVisible) { var length = allOverlays.length; - for (var i = 0; i < length; i++) { - Overlays.editOverlay(allOverlays[i], { + for (var overlayIndex = 0; overlayIndex < length; overlayIndex++) { + Overlays.editOverlay(allOverlays[overlayIndex], { visible: isVisible }); } length = selectionBoxes.length; - for (var i = 0; i < length; i++) { - Overlays.editOverlay(selectionBoxes[i], { + for (var boxIndex = 0; boxIndex < length; boxIndex++) { + Overlays.editOverlay(selectionBoxes[boxIndex], { visible: isVisible }); } }; + // FUNCTION: UNSELECT + // TODO?: Needs implementation that.unselect = function(entityID) {}; var initialXZPick = null; @@ -2350,6 +2358,7 @@ SelectionDisplay = (function() { var startPosition = null; var duplicatedEntityIDs = null; + // TOOL DEFINITION: TRANSLATE XZ TOOL var translateXZTool = { mode: 'TRANSLATE_XZ', pickPlanePosition: { x: 0, y: 0, z: 0 }, @@ -2538,7 +2547,8 @@ SelectionDisplay = (function() { } }; - var lastXYPick = null + // GRABBER TOOL: GRABBER MOVE UP + var lastXYPick = null; var upDownPickNormal = null; addGrabberTool(grabberMoveUp, { mode: "TRANSLATE_UP_DOWN", @@ -2594,7 +2604,7 @@ SelectionDisplay = (function() { print(" event.y:" + event.y); Vec3.print(" newIntersection:", newIntersection); Vec3.print(" vector:", vector); - Vec3.print(" newPosition:", newPosition); + //Vec3.print(" newPosition:", newPosition); } for (var i = 0; i < SelectionManager.selections.length; i++) { var id = SelectionManager.selections[i]; @@ -2612,6 +2622,7 @@ SelectionDisplay = (function() { }, }); + // GRABBER TOOL: GRABBER CLONER addGrabberTool(grabberCloner, { mode: "CLONE", onBegin: function(event) { @@ -2639,7 +2650,7 @@ SelectionDisplay = (function() { - + // FUNCTION: VEC 3 MULT var vec3Mult = function(v1, v2) { return { x: v1.x * v2.x, @@ -2647,6 +2658,8 @@ SelectionDisplay = (function() { z: v1.z * v2.z }; }; + + // FUNCTION: MAKE STRETCH TOOL // stretchMode - name of mode // direction - direction to stretch in // pivot - point to use as a pivot @@ -2898,13 +2911,14 @@ SelectionDisplay = (function() { // Are we using handControllers or Mouse - only relevant for 3D tools var controllerPose = getControllerWorldLocation(activeHand, true); - if (HMD.isHMDAvailable() - && HMD.isHandControllerAvailable() && controllerPose.valid && that.triggered && directionFor3DStretch) { + var vector = null; + if (HMD.isHMDAvailable() && HMD.isHandControllerAvailable() && + controllerPose.valid && that.triggered && directionFor3DStretch) { localDeltaPivot = deltaPivot3D; newPick = pickRay.origin; - var vector = Vec3.subtract(newPick, lastPick3D); + vector = Vec3.subtract(newPick, lastPick3D); vector = Vec3.multiplyQbyV(Quat.inverse(rotation), vector); @@ -2919,7 +2933,7 @@ SelectionDisplay = (function() { newPick = rayPlaneIntersection(pickRay, pickRayPosition, planeNormal); - var vector = Vec3.subtract(newPick, lastPick); + vector = Vec3.subtract(newPick, lastPick); vector = Vec3.multiplyQbyV(Quat.inverse(rotation), vector); @@ -2955,41 +2969,39 @@ SelectionDisplay = (function() { } else { newDimensions = Vec3.sum(initialDimensions, changeInDimensions); } - } - - - newDimensions.x = Math.max(newDimensions.x, MINIMUM_DIMENSION); - newDimensions.y = Math.max(newDimensions.y, MINIMUM_DIMENSION); - newDimensions.z = Math.max(newDimensions.z, MINIMUM_DIMENSION); - var changeInPosition = Vec3.multiplyQbyV(rotation, vec3Mult(localDeltaPivot, changeInDimensions)); - var newPosition = Vec3.sum(initialPosition, changeInPosition); + newDimensions.x = Math.max(newDimensions.x, MINIMUM_DIMENSION); + newDimensions.y = Math.max(newDimensions.y, MINIMUM_DIMENSION); + newDimensions.z = Math.max(newDimensions.z, MINIMUM_DIMENSION); - for (var i = 0; i < SelectionManager.selections.length; i++) { - Entities.editEntity(SelectionManager.selections[i], { - position: newPosition, - dimensions: newDimensions, - }); - } - + var changeInPosition = Vec3.multiplyQbyV(rotation, vec3Mult(localDeltaPivot, changeInDimensions)); + var newPosition = Vec3.sum(initialPosition, changeInPosition); - var wantDebug = false; - if (wantDebug) { - print(stretchMode); - //Vec3.print(" newIntersection:", newIntersection); - Vec3.print(" vector:", vector); - //Vec3.print(" oldPOS:", oldPOS); - //Vec3.print(" newPOS:", newPOS); - Vec3.print(" changeInDimensions:", changeInDimensions); - Vec3.print(" newDimensions:", newDimensions); + for (var i = 0; i < SelectionManager.selections.length; i++) { + Entities.editEntity(SelectionManager.selections[i], { + position: newPosition, + dimensions: newDimensions, + }); + } + - Vec3.print(" changeInPosition:", changeInPosition); - Vec3.print(" newPosition:", newPosition); + var wantDebug = false; + if (wantDebug) { + print(stretchMode); + //Vec3.print(" newIntersection:", newIntersection); + Vec3.print(" vector:", vector); + //Vec3.print(" oldPOS:", oldPOS); + //Vec3.print(" newPOS:", newPOS); + Vec3.print(" changeInDimensions:", changeInDimensions); + Vec3.print(" newDimensions:", newDimensions); + + Vec3.print(" changeInPosition:", changeInPosition); + Vec3.print(" newPosition:", newPosition); + } } SelectionManager._update(); - - }; + };//--End of onMove def return { mode: stretchMode, @@ -3042,7 +3054,8 @@ SelectionDisplay = (function() { z: -1 } }; - + + // FUNCTION: GET DIRECTION FOR 3D STRETCH // Returns a vector with directions for the stretch tool in 3D using hand controllers function getDirectionsFor3DStretch(mode) { if (mode === "STRETCH_LBN") { @@ -3067,7 +3080,7 @@ SelectionDisplay = (function() { } - + // FUNCTION: ADD STRETCH TOOL function addStretchTool(overlay, mode, pivot, direction, offset, handleMove) { if (!pivot) { pivot = direction; @@ -3077,6 +3090,7 @@ SelectionDisplay = (function() { addGrabberTool(overlay, tool); } + // FUNCTION: CUTOFF STRETCH FUNC function cutoffStretchFunc(vector, change) { vector = change; Vec3.print("Radius stretch: ", vector); @@ -3097,6 +3111,7 @@ SelectionDisplay = (function() { SelectionManager._update(); } + // FUNCTION: RADIUS STRETCH FUNC function radiusStretchFunc(vector, change) { var props = selectionManager.savedProperties[selectionManager.selections[0]]; @@ -3123,6 +3138,7 @@ SelectionDisplay = (function() { SelectionManager._update(); } + // STRETCH TOOL DEF SECTION addStretchTool(grabberNEAR, "STRETCH_NEAR", { x: 0, y: 0, @@ -3529,6 +3545,7 @@ SelectionDisplay = (function() { z: 1 }); + // FUNCTION: UPDATE ROTATION DEGREES OVERLAY function updateRotationDegreesOverlay(angleFromZero, handleRotation, centerPosition) { var angle = angleFromZero * (Math.PI / 180); var position = { @@ -3549,7 +3566,6 @@ SelectionDisplay = (function() { }); } - //----------------------------------------- // YAW GRABBER TOOL DEFINITION var initialPosition = SelectionManager.worldPosition; addGrabberTool(yawHandle, { @@ -3719,7 +3735,6 @@ SelectionDisplay = (function() { } }); - //----------------------------------------- // PITCH GRABBER TOOL DEFINITION addGrabberTool(pitchHandle, { mode: "ROTATE_PITCH", @@ -3793,7 +3808,6 @@ SelectionDisplay = (function() { var result = Overlays.findRayIntersection(pickRay, true, [rotateOverlayTarget]); if (result.intersects) { - var properties = Entities.getEntityProperties(selectionManager.selections[0]); var center = pitchCenter; var zero = pitchZero; var centerToZero = Vec3.subtract(zero, center); @@ -3815,7 +3829,6 @@ SelectionDisplay = (function() { for (var i = 0; i < SelectionManager.selections.length; i++) { var entityID = SelectionManager.selections[i]; - var properties = Entities.getEntityProperties(entityID); var initialProperties = SelectionManager.savedProperties[entityID]; var dPos = Vec3.subtract(initialProperties.position, initialPosition); dPos = Vec3.multiplyQbyV(pitchChange, dPos); @@ -3880,7 +3893,6 @@ SelectionDisplay = (function() { } }); - //----------------------------------------- // ROLL GRABBER TOOL DEFINITION addGrabberTool(rollHandle, { mode: "ROTATE_ROLL", @@ -3954,7 +3966,6 @@ SelectionDisplay = (function() { var result = Overlays.findRayIntersection(pickRay, true, [rotateOverlayTarget]); if (result.intersects) { - var properties = Entities.getEntityProperties(selectionManager.selections[0]); var center = rollCenter; var zero = rollZero; var centerToZero = Vec3.subtract(zero, center); @@ -3975,7 +3986,6 @@ SelectionDisplay = (function() { }); for (var i = 0; i < SelectionManager.selections.length; i++) { var entityID = SelectionManager.selections[i]; - var properties = Entities.getEntityProperties(entityID); var initialProperties = SelectionManager.savedProperties[entityID]; var dPos = Vec3.subtract(initialProperties.position, initialPosition); dPos = Vec3.multiplyQbyV(rollChange, dPos); @@ -4040,6 +4050,7 @@ SelectionDisplay = (function() { } }); + // FUNCTION: CHECK MOVE that.checkMove = function() { if (SelectionManager.hasSelection()) { @@ -4054,6 +4065,7 @@ SelectionDisplay = (function() { } }; + // FUNCTION: MOUSE PRESS EVENT that.mousePressEvent = function(event) { var wantDebug = false; if (!event.isLeftButton && !that.triggered) { @@ -4177,7 +4189,7 @@ SelectionDisplay = (function() { // Only intersect versus yaw/pitch/roll. - var result = Overlays.findRayIntersection(pickRay, true, [ yawHandle, pitchHandle, rollHandle ] ); + result = Overlays.findRayIntersection(pickRay, true, [ yawHandle, pitchHandle, rollHandle ] ); var overlayOrientation; var overlayCenter; @@ -4194,10 +4206,10 @@ SelectionDisplay = (function() { originalRoll = roll; if (result.intersects) { - var tool = grabberTools[result.overlayID]; - if (tool) { - activeTool = tool; - mode = tool.mode; + var resultTool = grabberTools[result.overlayID]; + if (resultTool) { + activeTool = resultTool; + mode = resultTool.mode; somethingClicked = 'tool'; if (activeTool && activeTool.onBegin) { activeTool.onBegin(event); @@ -4380,7 +4392,7 @@ SelectionDisplay = (function() { if (!somethingClicked) { // Only intersect versus selectionBox. - var result = Overlays.findRayIntersection(pickRay, true, [selectionBox]); + result = Overlays.findRayIntersection(pickRay, true, [selectionBox]); if (result.intersects) { switch (result.overlayID) { case selectionBox: @@ -4435,6 +4447,7 @@ SelectionDisplay = (function() { return somethingClicked; }; + // FUNCTION: MOUSE MOVE EVENT that.mouseMoveEvent = function(event) { if (activeTool) { activeTool.onMove(event); @@ -4564,7 +4577,7 @@ SelectionDisplay = (function() { return false; }; - + // FUNCTION: UPDATE HANDLE SIZES that.updateHandleSizes = function() { if (selectionManager.hasSelection()) { var diff = Vec3.subtract(selectionManager.worldPosition, Camera.getPosition()); @@ -4603,6 +4616,7 @@ SelectionDisplay = (function() { }; Script.update.connect(that.updateHandleSizes); + // FUNCTION: MOUSE RELEASE EVENT that.mouseReleaseEvent = function(event) { var showHandles = false; if (activeTool && activeTool.onEnd) { From ecd1f1319715c6ea1f88df151c29ef08210ddaca Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 16 Aug 2017 15:34:06 -0700 Subject: [PATCH 56/56] Allow users to take a snapshot from the secondary camera --- interface/src/Application.cpp | 6 ++++++ interface/src/Application.h | 1 + .../src/scripting/WindowScriptingInterface.cpp | 4 ++++ interface/src/scripting/WindowScriptingInterface.h | 1 + .../src/display-plugins/NullDisplayPlugin.cpp | 4 ++++ .../src/display-plugins/NullDisplayPlugin.h | 1 + .../src/display-plugins/OpenGLDisplayPlugin.cpp | 13 +++++++++++++ .../src/display-plugins/OpenGLDisplayPlugin.h | 1 + libraries/plugins/src/plugins/DisplayPlugin.h | 1 + 9 files changed, 32 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f954a1e2c4..616b6914e9 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6911,6 +6911,12 @@ void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRa }); } +void Application::takeSecondaryCameraSnapshot() { + postLambdaEvent([this] { + Snapshot::saveSnapshot(getActiveDisplayPlugin()->getSecondaryCameraScreenshot()); + }); +} + void Application::shareSnapshot(const QString& path, const QUrl& href) { postLambdaEvent([path, href] { // not much to do here, everything is done in snapshot code... diff --git a/interface/src/Application.h b/interface/src/Application.h index dddc373c91..752d6657fb 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -274,6 +274,7 @@ public: float getAverageSimsPerSecond() const { return _simCounter.rate(); } void takeSnapshot(bool notify, bool includeAnimated = false, float aspectRatio = 0.0f); + void takeSecondaryCameraSnapshot(); void shareSnapshot(const QString& filename, const QUrl& href = QUrl("")); model::SkyboxPointer getDefaultSkybox() const { return _defaultSkybox; } diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index 84f4cbbbd8..277989439c 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -294,6 +294,10 @@ void WindowScriptingInterface::takeSnapshot(bool notify, bool includeAnimated, f qApp->takeSnapshot(notify, includeAnimated, aspectRatio); } +void WindowScriptingInterface::takeSecondaryCameraSnapshot() { + qApp->takeSecondaryCameraSnapshot(); +} + void WindowScriptingInterface::shareSnapshot(const QString& path, const QUrl& href) { qApp->shareSnapshot(path, href); } diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index f8ed20f42f..28f1bafa5d 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -60,6 +60,7 @@ public slots: void showAssetServer(const QString& upload = ""); void copyToClipboard(const QString& text); void takeSnapshot(bool notify = true, bool includeAnimated = false, float aspectRatio = 0.0f); + void takeSecondaryCameraSnapshot(); void makeConnection(bool success, const QString& userNameOrError); void displayAnnouncement(const QString& message); void shareSnapshot(const QString& path, const QUrl& href = QUrl("")); diff --git a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp index a4777b087b..6a19a34727 100644 --- a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp @@ -34,3 +34,7 @@ void NullDisplayPlugin::submitFrame(const gpu::FramePointer& frame) { QImage NullDisplayPlugin::getScreenshot(float aspectRatio) const { return QImage(); } + +QImage NullDisplayPlugin::getSecondaryCameraScreenshot() const { + return QImage(); +} diff --git a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h index 8d01539e8a..97b71b5780 100644 --- a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h @@ -19,6 +19,7 @@ public: bool hasFocus() const override; void submitFrame(const gpu::FramePointer& newFrame) override; QImage getScreenshot(float aspectRatio = 0.0f) const override; + QImage getSecondaryCameraScreenshot() const override; void copyTextureToQuickFramebuffer(NetworkTexturePointer source, QOpenGLFramebufferObject* target, GLsync* fenceSync) override {}; private: static const QString NAME; diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index e1259fc5fc..7144e401e4 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -775,6 +775,19 @@ QImage OpenGLDisplayPlugin::getScreenshot(float aspectRatio) const { return screenshot.mirrored(false, true); } +QImage OpenGLDisplayPlugin::getSecondaryCameraScreenshot() const { + auto textureCache = DependencyManager::get(); + auto secondaryCameraFramebuffer = textureCache->getSpectatorCameraFramebuffer(); + gpu::Vec4i region(0, 0, secondaryCameraFramebuffer->getWidth(), secondaryCameraFramebuffer->getHeight()); + + auto glBackend = const_cast(*this).getGLBackend(); + QImage screenshot(region.z, region.w, QImage::Format_ARGB32); + withMainThreadContext([&] { + glBackend->downloadFramebuffer(secondaryCameraFramebuffer, region, screenshot); + }); + return screenshot.mirrored(false, true); +} + glm::uvec2 OpenGLDisplayPlugin::getSurfacePixels() const { uvec2 result; auto window = _container->getPrimaryWidget(); diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index 2f93fa630d..2080fa5ea6 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -60,6 +60,7 @@ public: virtual bool setDisplayTexture(const QString& name) override; virtual bool onDisplayTextureReset() { return false; }; QImage getScreenshot(float aspectRatio = 0.0f) const override; + QImage getSecondaryCameraScreenshot() const override; float presentRate() const override; diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index 9e18ee534d..d7531e66a7 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -183,6 +183,7 @@ public: // Fetch the most recently displayed image as a QImage virtual QImage getScreenshot(float aspectRatio = 0.0f) const = 0; + virtual QImage getSecondaryCameraScreenshot() const = 0; // will query the underlying hmd api to compute the most recent head pose virtual bool beginFrameRender(uint32_t frameIndex) { return true; }