From 5378cbead6dca1394abcb54784802587a3a86428 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 25 May 2017 13:47:03 -0700 Subject: [PATCH 01/16] make ObjectMotionState dtor virtual --- libraries/physics/src/ObjectMotionState.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/physics/src/ObjectMotionState.h b/libraries/physics/src/ObjectMotionState.h index 1e582ea854..ccdc0e0041 100644 --- a/libraries/physics/src/ObjectMotionState.h +++ b/libraries/physics/src/ObjectMotionState.h @@ -79,7 +79,7 @@ public: static ShapeManager* getShapeManager(); ObjectMotionState(const btCollisionShape* shape); - ~ObjectMotionState(); + virtual ~ObjectMotionState(); virtual void handleEasyChanges(uint32_t& flags); virtual bool handleHardAndEasyChanges(uint32_t& flags, PhysicsEngine* engine); From 3bd0c111d724fceba4bc6d205b5fbf77875eb3c7 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 25 May 2017 13:47:40 -0700 Subject: [PATCH 02/16] verify empty ShapeManager in Application dtor --- interface/src/Application.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5e3e09e778..2fe8677e1e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1682,6 +1682,10 @@ Application::~Application() { _physicsEngine->setCharacterController(nullptr); + // the _shapeManager should have zero references + _shapeManager.collectGarbage(); + assert(_shapeManager.getNumShapes() == 0); + // shutdown render engine _main3DScene = nullptr; _renderEngine = nullptr; From c22e4ef883eb3120de2bb29db8ccf152cdbd0595 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 25 May 2017 13:48:19 -0700 Subject: [PATCH 03/16] rename method to clarify where it is called --- libraries/physics/src/PhysicalEntitySimulation.cpp | 2 +- libraries/physics/src/PhysicsEngine.cpp | 2 +- libraries/physics/src/PhysicsEngine.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp index 2e69ff987c..fe507ed1ee 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.cpp +++ b/libraries/physics/src/PhysicalEntitySimulation.cpp @@ -130,7 +130,7 @@ void PhysicalEntitySimulation::clearEntitiesInternal() { } // then remove the objects (aka MotionStates) from physics - _physicsEngine->removeObjects(_physicalObjects); + _physicsEngine->removeSetOfObjects(_physicalObjects); // delete the MotionStates // TODO: after we invert the entities/physics lib dependencies we will let EntityItem delete diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 3a02e95e7c..1d61e53fbb 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -207,7 +207,7 @@ void PhysicsEngine::removeObjects(const VectorOfMotionStates& objects) { } // Same as above, but takes a Set instead of a Vector. Should only be called during teardown. -void PhysicsEngine::removeObjects(const SetOfMotionStates& objects) { +void PhysicsEngine::removeSetOfObjects(const SetOfMotionStates& objects) { _contactMap.clear(); for (auto object : objects) { btRigidBody* body = object->getRigidBody(); diff --git a/libraries/physics/src/PhysicsEngine.h b/libraries/physics/src/PhysicsEngine.h index e9b29a43a4..c029d14a42 100644 --- a/libraries/physics/src/PhysicsEngine.h +++ b/libraries/physics/src/PhysicsEngine.h @@ -53,7 +53,7 @@ public: uint32_t getNumSubsteps(); void removeObjects(const VectorOfMotionStates& objects); - void removeObjects(const SetOfMotionStates& objects); // only called during teardown + void removeSetOfObjects(const SetOfMotionStates& objects); // only called during teardown void addObjects(const VectorOfMotionStates& objects); VectorOfMotionStates changeObjects(const VectorOfMotionStates& objects); From 971855e6bf91ca863c38e057bb01bb0102018753 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 25 May 2017 14:29:14 -0700 Subject: [PATCH 04/16] add asserts to catch dangling pointers sooner --- libraries/physics/src/EntityMotionState.cpp | 2 ++ libraries/physics/src/ObjectMotionState.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index fdd290bfca..adb7bbddde 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -114,6 +114,7 @@ void EntityMotionState::handleDeactivation() { // virtual void EntityMotionState::handleEasyChanges(uint32_t& flags) { + assert(_entity); assert(entityTreeIsLocked()); updateServerPhysicsVariables(); ObjectMotionState::handleEasyChanges(flags); @@ -170,6 +171,7 @@ void EntityMotionState::handleEasyChanges(uint32_t& flags) { // virtual bool EntityMotionState::handleHardAndEasyChanges(uint32_t& flags, PhysicsEngine* engine) { + assert(_entity); updateServerPhysicsVariables(); return ObjectMotionState::handleHardAndEasyChanges(flags, engine); } diff --git a/libraries/physics/src/ObjectMotionState.cpp b/libraries/physics/src/ObjectMotionState.cpp index a877887840..b11e21366e 100644 --- a/libraries/physics/src/ObjectMotionState.cpp +++ b/libraries/physics/src/ObjectMotionState.cpp @@ -202,6 +202,7 @@ void ObjectMotionState::setShape(const btCollisionShape* shape) { } void ObjectMotionState::handleEasyChanges(uint32_t& flags) { + assert(_body && _shape); if (flags & Simulation::DIRTY_POSITION) { btTransform worldTrans = _body->getWorldTransform(); btVector3 newPosition = glmToBullet(getObjectPosition()); @@ -282,6 +283,7 @@ void ObjectMotionState::handleEasyChanges(uint32_t& flags) { } bool ObjectMotionState::handleHardAndEasyChanges(uint32_t& flags, PhysicsEngine* engine) { + assert(_body && _shape); if (flags & Simulation::DIRTY_SHAPE) { // make sure the new shape is valid if (!isReadyToComputeShape()) { From fa003b0c14bddfef711f175dcd629525ce3b2f29 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 26 May 2017 12:29:37 -0700 Subject: [PATCH 05/16] swap order of changes and deactvations --- interface/src/Application.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2fe8677e1e..71efbd52f3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4485,12 +4485,13 @@ void Application::update(float deltaTime) { getEntities()->getTree()->withWriteLock([&] { PerformanceTimer perfTimer("handleOutgoingChanges"); - const VectorOfMotionStates& deactivations = _physicsEngine->getDeactivatedMotionStates(); - _entitySimulation->handleDeactivatedMotionStates(deactivations); const VectorOfMotionStates& outgoingChanges = _physicsEngine->getChangedMotionStates(); _entitySimulation->handleChangedMotionStates(outgoingChanges); avatarManager->handleChangedMotionStates(outgoingChanges); + + const VectorOfMotionStates& deactivations = _physicsEngine->getDeactivatedMotionStates(); + _entitySimulation->handleDeactivatedMotionStates(deactivations); }); if (!_aboutToQuit) { From bcee25acc7317575a668df88046f169df0462492 Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Sun, 28 May 2017 19:54:41 +0200 Subject: [PATCH 06/16] Make sure that there is only one connection created for web events, so downloads from CLARA IO not duplicated --- .../resources/qml/hifi/tablet/TabletRoot.qml | 20 +++++++++++-------- .../resources/qml/hifi/tablet/WindowRoot.qml | 19 +++++++++++------- scripts/system/edit.js | 8 +++++++- scripts/system/libraries/entityList.js | 8 +++++++- scripts/system/libraries/gridTool.js | 8 +++++++- 5 files changed, 45 insertions(+), 18 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/TabletRoot.qml b/interface/resources/qml/hifi/tablet/TabletRoot.qml index 33af7da1ae..97c8854c86 100644 --- a/interface/resources/qml/hifi/tablet/TabletRoot.qml +++ b/interface/resources/qml/hifi/tablet/TabletRoot.qml @@ -170,20 +170,24 @@ Item { objectName: "loader" asynchronous: false - width: parent.width height: parent.height + // Hook up callback for clara.io download from the marketplace. + Connections { + id: eventBridgeConnection + target: null + onWebEventReceived: { + if (message.slice(0, 17) === "CLARA.IO DOWNLOAD") { + ApplicationInterface.addAssetToWorldFromURL(message.slice(18)); + } + } + } + onLoaded: { if (loader.item.hasOwnProperty("eventBridge")) { loader.item.eventBridge = eventBridge; - - // Hook up callback for clara.io download from the marketplace. - eventBridge.webEventReceived.connect(function (event) { - if (event.slice(0, 17) === "CLARA.IO DOWNLOAD") { - ApplicationInterface.addAssetToWorldFromURL(event.slice(18)); - } - }); + eventBridgeConnection.target = eventBridge } if (loader.item.hasOwnProperty("sendToScript")) { loader.item.sendToScript.connect(tabletRoot.sendToScript); diff --git a/interface/resources/qml/hifi/tablet/WindowRoot.qml b/interface/resources/qml/hifi/tablet/WindowRoot.qml index 470fd4a830..ee8dbbff59 100644 --- a/interface/resources/qml/hifi/tablet/WindowRoot.qml +++ b/interface/resources/qml/hifi/tablet/WindowRoot.qml @@ -90,16 +90,21 @@ Windows.ScrollingWindow { anchors.left: parent.left anchors.top: parent.top + // Hook up callback for clara.io download from the marketplace. + Connections { + id: eventBridgeConnection + target: null + onWebEventReceived: { + if (message.slice(0, 17) === "CLARA.IO DOWNLOAD") { + ApplicationInterface.addAssetToWorldFromURL(message.slice(18)); + } + } + } + onLoaded: { if (loader.item.hasOwnProperty("eventBridge")) { loader.item.eventBridge = eventBridge; - - // Hook up callback for clara.io download from the marketplace. - eventBridge.webEventReceived.connect(function (event) { - if (event.slice(0, 17) === "CLARA.IO DOWNLOAD") { - ApplicationInterface.addAssetToWorldFromURL(event.slice(18)); - } - }); + eventBridgeConnection.target = eventBridge } if (loader.item.hasOwnProperty("sendToScript")) { loader.item.sendToScript.connect(tabletRoot.sendToScript); diff --git a/scripts/system/edit.js b/scripts/system/edit.js index f39165f3df..6a1ede88c6 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -2100,7 +2100,13 @@ function selectParticleEntity(entityID) { } entityListTool.webView.webEventReceived.connect(function (data) { - data = JSON.parse(data); + try { + data = JSON.parse(data); + } catch(e) { + print("edit.js: Error parsing JSON: " + e.name + " data " + data) + return; + } + if (data.type === 'parent') { parentSelectedEntities(); } else if(data.type === 'unparent') { diff --git a/scripts/system/libraries/entityList.js b/scripts/system/libraries/entityList.js index 3b6d32ec1c..64a05fcebf 100644 --- a/scripts/system/libraries/entityList.js +++ b/scripts/system/libraries/entityList.js @@ -109,7 +109,13 @@ EntityListTool = function(opts) { }; webView.webEventReceived.connect(function(data) { - data = JSON.parse(data); + try { + data = JSON.parse(data); + } catch(e) { + print("entityList.js: Error parsing JSON: " + e.name + " data " + data) + return; + } + if (data.type == "selectionUpdate") { var ids = data.entityIds; var entityIDs = []; diff --git a/scripts/system/libraries/gridTool.js b/scripts/system/libraries/gridTool.js index 0290674a0f..de9596e9be 100644 --- a/scripts/system/libraries/gridTool.js +++ b/scripts/system/libraries/gridTool.js @@ -238,7 +238,13 @@ GridTool = function(opts) { }); webView.webEventReceived.connect(function(data) { - data = JSON.parse(data); + try { + data = JSON.parse(data); + } catch(e) { + print("gridTool.js: Error parsing JSON: " + e.name + " data " + data) + return; + } + if (data.type == "init") { horizontalGrid.emitUpdate(); } else if (data.type == "update") { From a1e073792809f3f1f8f7aa09204c5390e815e181 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 1 Jun 2017 18:06:06 +0100 Subject: [PATCH 07/16] saving work --- .../controllers/src/controllers/UserInputMapper.cpp | 10 ++++++++++ .../controllers/src/controllers/UserInputMapper.h | 1 + .../controllers/impl/endpoints/ActionEndpoint.cpp | 2 +- .../controllers/impl/endpoints/StandardEndpoint.h | 12 ++++++++++++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/libraries/controllers/src/controllers/UserInputMapper.cpp b/libraries/controllers/src/controllers/UserInputMapper.cpp index 570081d1f1..bd0eeda6bd 100755 --- a/libraries/controllers/src/controllers/UserInputMapper.cpp +++ b/libraries/controllers/src/controllers/UserInputMapper.cpp @@ -329,6 +329,16 @@ QString UserInputMapper::getActionName(Action action) const { return QString(); } +QString UserInputMapper::getStandardPoseName(uint16_t pose) { + Locker locker(_lock); + for (auto posePair : getStandardInputs()) { + if (posePair.first.channel == pose) { + return posePair.second; + } + } + return QString(); +} + QVector UserInputMapper::getActionNames() const { Locker locker(_lock); QVector result; diff --git a/libraries/controllers/src/controllers/UserInputMapper.h b/libraries/controllers/src/controllers/UserInputMapper.h index 05a286cc10..0c8bb51008 100644 --- a/libraries/controllers/src/controllers/UserInputMapper.h +++ b/libraries/controllers/src/controllers/UserInputMapper.h @@ -80,6 +80,7 @@ namespace controller { QVector getAllActions() const; QString getActionName(Action action) const; + QString getStandardPoseName(uint16_t pose); float getActionState(Action action) const { return _actionStates[toInt(action)]; } Pose getPoseState(Action action) const; int findAction(const QString& actionName) const; diff --git a/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.cpp b/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.cpp index eb834a0bf2..f1bdae1e0b 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.cpp +++ b/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.cpp @@ -37,7 +37,7 @@ void ActionEndpoint::apply(const Pose& value, const Pointer& source) { QString actionName = userInputMapper->getActionName(Action(_input.getChannel())); inputRecorder->setActionState(actionName, _currentPose); if (inputRecorder->isPlayingback()) { - _currentPose = inputRecorder->getPoseState(actionName); + //_currentPose = inputRecorder->getPoseState(actionName); } if (!_currentPose.isValid()) { diff --git a/libraries/controllers/src/controllers/impl/endpoints/StandardEndpoint.h b/libraries/controllers/src/controllers/impl/endpoints/StandardEndpoint.h index dfa728d2b6..f6d04b8c86 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/StandardEndpoint.h +++ b/libraries/controllers/src/controllers/impl/endpoints/StandardEndpoint.h @@ -12,6 +12,11 @@ #include "../Endpoint.h" +#include + +#include "../../InputRecorder.h" +#include "../../UserInputMapper.h" + namespace controller { class StandardEndpoint : public VirtualEndpoint { @@ -40,6 +45,13 @@ public: virtual Pose pose() override { _read = true; + InputRecorder* inputRecorder = InputRecorder::getInstance(); + if (inputRecorder->isPlayingback()) { + auto userInputMapper = DependencyManager::get(); + QString actionName = userInputMapper->getStandardPoseName(_input.getChannel()); + qDebug() << actionName; + return inputRecorder->getPoseState(actionName); + } return VirtualEndpoint::pose(); } From e52765b64119b235ad32510f9fe119280d39bd68 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 1 Jun 2017 18:51:24 +0100 Subject: [PATCH 08/16] playback recording back through the standard inputs --- libraries/controllers/src/controllers/UserInputMapper.cpp | 2 +- .../src/controllers/impl/endpoints/ActionEndpoint.cpp | 3 --- .../src/controllers/impl/endpoints/StandardEndpoint.h | 1 - 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/libraries/controllers/src/controllers/UserInputMapper.cpp b/libraries/controllers/src/controllers/UserInputMapper.cpp index bd0eeda6bd..79f4325ae6 100755 --- a/libraries/controllers/src/controllers/UserInputMapper.cpp +++ b/libraries/controllers/src/controllers/UserInputMapper.cpp @@ -332,7 +332,7 @@ QString UserInputMapper::getActionName(Action action) const { QString UserInputMapper::getStandardPoseName(uint16_t pose) { Locker locker(_lock); for (auto posePair : getStandardInputs()) { - if (posePair.first.channel == pose) { + if (posePair.first.channel == pose && posePair.first.getType() == ChannelType::POSE) { return posePair.second; } } diff --git a/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.cpp b/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.cpp index f1bdae1e0b..ef9f04402b 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.cpp +++ b/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.cpp @@ -36,9 +36,6 @@ void ActionEndpoint::apply(const Pose& value, const Pointer& source) { auto userInputMapper = DependencyManager::get(); QString actionName = userInputMapper->getActionName(Action(_input.getChannel())); inputRecorder->setActionState(actionName, _currentPose); - if (inputRecorder->isPlayingback()) { - //_currentPose = inputRecorder->getPoseState(actionName); - } if (!_currentPose.isValid()) { return; diff --git a/libraries/controllers/src/controllers/impl/endpoints/StandardEndpoint.h b/libraries/controllers/src/controllers/impl/endpoints/StandardEndpoint.h index f6d04b8c86..2006809fed 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/StandardEndpoint.h +++ b/libraries/controllers/src/controllers/impl/endpoints/StandardEndpoint.h @@ -49,7 +49,6 @@ public: if (inputRecorder->isPlayingback()) { auto userInputMapper = DependencyManager::get(); QString actionName = userInputMapper->getStandardPoseName(_input.getChannel()); - qDebug() << actionName; return inputRecorder->getPoseState(actionName); } return VirtualEndpoint::pose(); From 3d98f1b3eebc605cc2bcbed823e3c172a573e208 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 1 Jun 2017 13:46:37 -0700 Subject: [PATCH 09/16] print metaverse session ID to debug log --- libraries/networking/src/AccountManager.cpp | 7 +++++++ libraries/networking/src/AccountManager.h | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index 6266ad0f89..85232f9f61 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -201,6 +201,13 @@ void AccountManager::setAuthURL(const QUrl& authURL) { } } +void AccountManager::setSessionID(const QUuid& sessionID) { + if (_sessionID != sessionID) { + qCDebug(networking) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(sessionID); + _sessionID = sessionID; + } +} + void AccountManager::sendRequest(const QString& path, AccountManagerAuth::Type authType, QNetworkAccessManager::Operation operation, diff --git a/libraries/networking/src/AccountManager.h b/libraries/networking/src/AccountManager.h index dd2216957f..9a456ca7e8 100644 --- a/libraries/networking/src/AccountManager.h +++ b/libraries/networking/src/AccountManager.h @@ -90,7 +90,7 @@ public: static QJsonObject dataObjectFromResponse(QNetworkReply& requestReply); QUuid getSessionID() const { return _sessionID; } - void setSessionID(const QUuid& sessionID) { _sessionID = sessionID; } + void setSessionID(const QUuid& sessionID); void setTemporaryDomain(const QUuid& domainID, const QString& key); const QString& getTemporaryDomainKey(const QUuid& domainID) { return _accountInfo.getTemporaryDomainKey(domainID); } From 2a5c43026ae495b529814a85622ecf945ac909eb Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 1 Jun 2017 22:27:51 +0100 Subject: [PATCH 10/16] gzip recording data --- .../src/controllers/InputRecorder.cpp | 70 ++++++++----------- 1 file changed, 30 insertions(+), 40 deletions(-) diff --git a/libraries/controllers/src/controllers/InputRecorder.cpp b/libraries/controllers/src/controllers/InputRecorder.cpp index e8bcd3a006..f98a42ccd2 100644 --- a/libraries/controllers/src/controllers/InputRecorder.cpp +++ b/libraries/controllers/src/controllers/InputRecorder.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -93,23 +94,26 @@ namespace controller { } - void exportToFile(const QJsonObject& object) { + void exportToFile(const QJsonObject& object, const QString& fileName) { if (!QDir(SAVE_DIRECTORY).exists()) { QDir().mkdir(SAVE_DIRECTORY); } - - QString timeStamp = QDateTime::currentDateTime().toString(Qt::ISODate); - timeStamp.replace(":", "-"); - QString fileName = SAVE_DIRECTORY + FILE_PREFIX_NAME + timeStamp + COMPRESS_EXTENSION; - qDebug() << fileName; + QFile saveFile (fileName); if (!saveFile.open(QIODevice::WriteOnly)) { qWarning() << "could not open file: " << fileName; return; } QJsonDocument saveData(object); - QByteArray compressedData = qCompress(saveData.toJson(QJsonDocument::Compact)); - saveFile.write(compressedData); + QByteArray jsonData = saveData.toJson(QJsonDocument::Indented); + QByteArray jsonDataForFile; + + if (!gzip(jsonData, jsonDataForFile, -1)) { + qCritical("unable to gzip while saving to json."); + return; + } + + saveFile.write(jsonDataForFile); saveFile.close(); } @@ -121,8 +125,16 @@ namespace controller { status = false; return object; } - QByteArray compressedData = qUncompress(openFile.readAll()); - QJsonDocument jsonDoc = QJsonDocument::fromJson(compressedData); + QByteArray compressedData = openFile.readAll(); + QByteArray jsonData; + + if (!gunzip(compressedData, jsonData)) { + qCritical() << "json file not in gzip format: " << file; + status = false; + return object; + } + + QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData); object = jsonDoc.object(); status = true; openFile.close(); @@ -153,7 +165,7 @@ namespace controller { QJsonObject InputRecorder::recordDataToJson() { QJsonObject data; data["frameCount"] = _framesRecorded; - data["version"] = "1.0"; + data["version"] = "0.0"; QJsonArray actionArrayList; QJsonArray poseArrayList; @@ -187,7 +199,10 @@ namespace controller { void InputRecorder::saveRecording() { QJsonObject jsonData = recordDataToJson(); - exportToFile(jsonData); + QString timeStamp = QDateTime::currentDateTime().toString(Qt::ISODate); + timeStamp.replace(":", "-"); + QString fileName = SAVE_DIRECTORY + FILE_PREFIX_NAME + timeStamp + COMPRESS_EXTENSION; + exportToFile(jsonData, fileName); } void InputRecorder::loadRecording(const QString& path) { @@ -202,10 +217,12 @@ namespace controller { QString filePath = urlPath.toLocalFile(); QFileInfo info(filePath); QString extension = info.suffix(); + if (extension != "gz") { qWarning() << "can not load file with exentsion of " << extension; return; } + bool success = false; QJsonObject data = openFile(filePath, success); auto keyValue = data.find("version"); @@ -233,34 +250,7 @@ namespace controller { _poseStateList.push_back(_currentFramePoses); _currentFramePoses.clear(); } - } else if (success) { - //convert recording to new reacording standard and rewrite file - auto userInputMapper = DependencyManager::get(); - _framesRecorded = data["frameCount"].toInt(); - QJsonArray actionArrayList = data["actionList"].toArray(); - QJsonArray poseArrayList = data["poseList"].toArray(); - - for (int actionIndex = 0; actionIndex < actionArrayList.size(); actionIndex++) { - QJsonArray actionState = actionArrayList[actionIndex].toArray(); - for (int index = 0; index < actionState.size(); index++) { - QString actionName = userInputMapper->getActionName(Action(index)); - _currentFrameActions[actionName] = actionState[index].toDouble(); - } - _actionStateList.push_back(_currentFrameActions); - _currentFrameActions.clear(); - } - - for (int poseIndex = 0; poseIndex < poseArrayList.size(); poseIndex++) { - QJsonArray poseState = poseArrayList[poseIndex].toArray(); - for (int index = 0; index < poseState.size(); index++) { - QString actionName = userInputMapper->getActionName(Action(index)); - _currentFramePoses[actionName] = jsonObjectToPose(poseState[index].toObject()); - } - _poseStateList.push_back(_currentFramePoses); - _currentFramePoses.clear(); - } - } - + } _loading = false; } From 77eb75db95db709c38f93c6759524a81eb5ad2a0 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 1 Jun 2017 22:48:59 +0100 Subject: [PATCH 11/16] add .json to extension --- libraries/controllers/src/controllers/InputRecorder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/controllers/src/controllers/InputRecorder.cpp b/libraries/controllers/src/controllers/InputRecorder.cpp index d52d7d4f09..54d1aaf131 100644 --- a/libraries/controllers/src/controllers/InputRecorder.cpp +++ b/libraries/controllers/src/controllers/InputRecorder.cpp @@ -28,7 +28,7 @@ QString SAVE_DIRECTORY = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/" + BuildInfo::MODIFIED_ORGANIZATION + "/" + BuildInfo::INTERFACE_NAME + "/hifi-input-recordings/"; QString FILE_PREFIX_NAME = "input-recording-"; -QString COMPRESS_EXTENSION = "json.gz"; +QString COMPRESS_EXTENSION = ".json.gz"; namespace controller { QJsonObject poseToJsonObject(const Pose pose) { From 06b3ecfdc3072a5a90dab3e21ae1915f3d2bddfc Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 1 Jun 2017 15:50:56 -0700 Subject: [PATCH 12/16] also log metaverse session ID during ctor of AccountManager --- libraries/networking/src/AccountManager.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index 85232f9f61..ab336b0b31 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -90,6 +90,8 @@ AccountManager::AccountManager(UserAgentGetter userAgentGetter) : qRegisterMetaType("QHttpMultiPart*"); qRegisterMetaType(); + + qCDebug(networking) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(_sessionID); } const QString DOUBLE_SLASH_SUBSTITUTE = "slashslash"; @@ -203,7 +205,7 @@ void AccountManager::setAuthURL(const QUrl& authURL) { void AccountManager::setSessionID(const QUuid& sessionID) { if (_sessionID != sessionID) { - qCDebug(networking) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(sessionID); + qCDebug(networking) << "Metaverse session ID changed to" << uuidStringWithoutCurlyBraces(sessionID); _sessionID = sessionID; } } From 0f22b07026be8558ba18041f8d545bf77f6f80b2 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 1 Jun 2017 16:07:36 -0700 Subject: [PATCH 13/16] move session ID logging later in app startup --- interface/src/Application.cpp | 2 ++ libraries/networking/src/AccountManager.cpp | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 46c4c0bd4e..8c6bea0905 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1459,6 +1459,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo updateSystemTabletMode(); connect(&_myCamera, &Camera::modeUpdated, this, &Application::cameraModeChanged); + + qCDebug(interfaceapp) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(accountManager->getSessionID()); } void Application::domainConnectionRefused(const QString& reasonMessage, int reasonCodeInt, const QString& extraInfo) { diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index ab336b0b31..c6fffbfdbd 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -90,8 +90,6 @@ AccountManager::AccountManager(UserAgentGetter userAgentGetter) : qRegisterMetaType("QHttpMultiPart*"); qRegisterMetaType(); - - qCDebug(networking) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(_sessionID); } const QString DOUBLE_SLASH_SUBSTITUTE = "slashslash"; From 37b738ff8bba90ad2784a09a1e9060f5366b555e Mon Sep 17 00:00:00 2001 From: David Kelly Date: Thu, 1 Jun 2017 16:46:31 -0700 Subject: [PATCH 14/16] initial cut at some UserActivities for the bubble --- .../src/UserActivityLoggerScriptingInterface.cpp | 10 +++++++++- .../src/UserActivityLoggerScriptingInterface.h | 2 ++ scripts/system/bubble.js | 4 +++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/UserActivityLoggerScriptingInterface.cpp b/libraries/networking/src/UserActivityLoggerScriptingInterface.cpp index ff69363570..61f2071c5f 100644 --- a/libraries/networking/src/UserActivityLoggerScriptingInterface.cpp +++ b/libraries/networking/src/UserActivityLoggerScriptingInterface.cpp @@ -56,7 +56,7 @@ void UserActivityLoggerScriptingInterface::palAction(QString action, QString tar } void UserActivityLoggerScriptingInterface::palOpened(float secondsOpened) { - doLogAction("pal_opened", { + doLogAction("pal_opened", { { "seconds_opened", secondsOpened } }); } @@ -71,6 +71,14 @@ void UserActivityLoggerScriptingInterface::makeUserConnection(QString otherID, b doLogAction("makeUserConnection", payload); } +void UserActivityLoggerScriptingInterface::bubbleToggled(bool newValue) { + doLogAction(newValue ? "bubbleOn" : "bubbleOff"); +} + +void UserActivityLoggerScriptingInterface::bubbleActivated() { + doLogAction("bubbleActivated"); +} + void UserActivityLoggerScriptingInterface::logAction(QString action, QVariantMap details) { doLogAction(action, QJsonObject::fromVariantMap(details)); } diff --git a/libraries/networking/src/UserActivityLoggerScriptingInterface.h b/libraries/networking/src/UserActivityLoggerScriptingInterface.h index b141e930f2..885f637a62 100644 --- a/libraries/networking/src/UserActivityLoggerScriptingInterface.h +++ b/libraries/networking/src/UserActivityLoggerScriptingInterface.h @@ -30,6 +30,8 @@ public: Q_INVOKABLE void palAction(QString action, QString target); Q_INVOKABLE void palOpened(float secondsOpen); Q_INVOKABLE void makeUserConnection(QString otherUser, bool success, QString details = ""); + Q_INVOKABLE void bubbleToggled(bool newValue); + Q_INVOKABLE void bubbleActivated(); Q_INVOKABLE void logAction(QString action, QVariantMap details = QVariantMap{}); private: void doLogAction(QString action, QJsonObject details = {}); diff --git a/scripts/system/bubble.js b/scripts/system/bubble.js index 8d103c93de..de18bae4cd 100644 --- a/scripts/system/bubble.js +++ b/scripts/system/bubble.js @@ -10,7 +10,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* global Script, Users, Overlays, AvatarList, Controller, Camera, getControllerWorldLocation */ +/* global Script, Users, Overlays, AvatarList, Controller, Camera, getControllerWorldLocation, UserActivityLogger */ (function () { // BEGIN LOCAL_SCOPE var button; @@ -76,6 +76,7 @@ // Called from the C++ scripting interface to show the bubble overlay function enteredIgnoreRadius() { createOverlays(); + UserActivityLogger.bubbleActivated(); } // Used to set the state of the bubble HUD button @@ -142,6 +143,7 @@ function onBubbleToggled() { var bubbleActive = Users.getIgnoreRadiusEnabled(); writeButtonProperties(bubbleActive); + UserActivityLogger.bubbleToggled(bubbleActive); if (bubbleActive) { createOverlays(); } else { From 4dae77cd9d382d5d8162f1df5fb7335f4a82d888 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Fri, 2 Jun 2017 08:45:02 -0700 Subject: [PATCH 15/16] make sure we dont log the initial call to onBubbleToggled --- scripts/system/bubble.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/scripts/system/bubble.js b/scripts/system/bubble.js index de18bae4cd..1bdc14368c 100644 --- a/scripts/system/bubble.js +++ b/scripts/system/bubble.js @@ -140,11 +140,12 @@ } // When the space bubble is toggled... - function onBubbleToggled() { - var bubbleActive = Users.getIgnoreRadiusEnabled(); - writeButtonProperties(bubbleActive); - UserActivityLogger.bubbleToggled(bubbleActive); - if (bubbleActive) { + function onBubbleToggled(enabled, doNotLog) { + writeButtonProperties(enabled); + if (doNotLog !== true) { + UserActivityLogger.bubbleToggled(enabled); + } + if (enabled) { createOverlays(); } else { hideOverlays(); @@ -165,7 +166,7 @@ sortOrder: 4 }); - onBubbleToggled(); + onBubbleToggled(Users.getIgnoreRadiusEnabled(), true); // pass in true so we don't log this initial one in the UserActivity table button.clicked.connect(Users.toggleIgnoreRadius); Users.ignoreRadiusEnabledChanged.connect(onBubbleToggled); From 2feea16063bd5c958e82773275bf2666e2153490 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Fri, 2 Jun 2017 09:47:03 -0700 Subject: [PATCH 16/16] added comment --- scripts/system/bubble.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/system/bubble.js b/scripts/system/bubble.js index 1bdc14368c..c2a2f7af40 100644 --- a/scripts/system/bubble.js +++ b/scripts/system/bubble.js @@ -140,6 +140,8 @@ } // When the space bubble is toggled... + // NOTE: the c++ calls this with just the first param -- we added a second + // just for not logging the initial state of the bubble when we startup. function onBubbleToggled(enabled, doNotLog) { writeButtonProperties(enabled); if (doNotLog !== true) {