From 2f3fa80b96eab8a8130fcb6be580932c38e74f00 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 26 May 2016 09:52:22 +1200 Subject: [PATCH 1/5] Add Clipboard.getContentsDimensions() JavaScript method --- interface/src/scripting/ClipboardScriptingInterface.cpp | 4 ++++ interface/src/scripting/ClipboardScriptingInterface.h | 1 + libraries/entities/src/EntityTree.cpp | 7 +++++++ libraries/entities/src/EntityTree.h | 1 + 4 files changed, 13 insertions(+) diff --git a/interface/src/scripting/ClipboardScriptingInterface.cpp b/interface/src/scripting/ClipboardScriptingInterface.cpp index b0ef6c760d..b803080538 100644 --- a/interface/src/scripting/ClipboardScriptingInterface.cpp +++ b/interface/src/scripting/ClipboardScriptingInterface.cpp @@ -14,6 +14,10 @@ ClipboardScriptingInterface::ClipboardScriptingInterface() { } +glm::vec3 ClipboardScriptingInterface::getContentsDimensions() { + return qApp->getEntityClipboard()->getContentsDimensions(); +} + float ClipboardScriptingInterface::getClipboardContentsLargestDimension() { return qApp->getEntityClipboard()->getContentsLargestDimension(); } diff --git a/interface/src/scripting/ClipboardScriptingInterface.h b/interface/src/scripting/ClipboardScriptingInterface.h index 73bebd4836..4737a194df 100644 --- a/interface/src/scripting/ClipboardScriptingInterface.h +++ b/interface/src/scripting/ClipboardScriptingInterface.h @@ -22,6 +22,7 @@ signals: void readyToImport(); public slots: + glm::vec3 getContentsDimensions(); /// returns the overall dimensions of everything on the blipboard float getClipboardContentsLargestDimension(); /// returns the largest dimension of everything on the clipboard bool importEntities(const QString& filename); bool exportEntities(const QString& filename, const QVector& entityIDs); diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index b85ee1dcf9..581e0a9568 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1284,6 +1284,7 @@ class ContentsDimensionOperator : public RecurseOctreeOperator { public: virtual bool preRecursion(OctreeElementPointer element); virtual bool postRecursion(OctreeElementPointer element) { return true; } + glm::vec3 getDimensions() const { return _contentExtents.size(); } float getLargestDimension() const { return _contentExtents.largestDimension(); } private: Extents _contentExtents; @@ -1295,6 +1296,12 @@ bool ContentsDimensionOperator::preRecursion(OctreeElementPointer element) { return true; } +glm::vec3 EntityTree::getContentsDimensions() { + ContentsDimensionOperator theOperator; + recurseTreeWithOperator(&theOperator); + return theOperator.getDimensions(); +} + float EntityTree::getContentsLargestDimension() { ContentsDimensionOperator theOperator; recurseTreeWithOperator(&theOperator); diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 03b8a9b55a..a85624c9ae 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -207,6 +207,7 @@ public: bool skipThoseWithBadParents) override; virtual bool readFromMap(QVariantMap& entityDescription) override; + glm::vec3 getContentsDimensions(); float getContentsLargestDimension(); virtual void resetEditStats() override { From 44fe7c11443ddab37f97ec8a85ffad17cc3831d9 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 2 Jun 2016 21:26:33 +1200 Subject: [PATCH 2/5] Add Entities.getChildrenIDs() method --- .../entities/src/EntityScriptingInterface.cpp | 21 +++++++++++++++++++ .../entities/src/EntityScriptingInterface.h | 1 + 2 files changed, 22 insertions(+) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 15c2bffd80..d09fc60d9b 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -1121,6 +1121,27 @@ QStringList EntityScriptingInterface::getJointNames(const QUuid& entityID) { return result; } +QVector EntityScriptingInterface::getChildrenIDs(const QUuid& parentID) { + QVector result; + if (!_entityTree) { + return result; + } + + EntityItemPointer entity = _entityTree->findEntityByEntityItemID(parentID); + if (!entity) { + qDebug() << "EntityScriptingInterface::getChildrenIDs - no entity with ID" << parentID; + return result; + } + + _entityTree->withReadLock([&] { + entity->forEachChild([&](SpatiallyNestablePointer child) { + result.push_back(child->getID()); + }); + }); + + return result; +} + QVector EntityScriptingInterface::getChildrenIDsOfJoint(const QUuid& parentID, int jointIndex) { QVector result; if (!_entityTree) { diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 2f5446874b..8ae6a77dab 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -171,6 +171,7 @@ public slots: Q_INVOKABLE int getJointIndex(const QUuid& entityID, const QString& name); Q_INVOKABLE QStringList getJointNames(const QUuid& entityID); + Q_INVOKABLE QVector getChildrenIDs(const QUuid& parentID); Q_INVOKABLE QVector getChildrenIDsOfJoint(const QUuid& parentID, int jointIndex); signals: From 8f9fc08226d3df4059f8f00403d588799815a060 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 3 Jun 2016 11:08:05 -0700 Subject: [PATCH 3/5] Add version number to avatar recording frame New recordings will have a version number of 1. A missing version field indicates the initial version of 0. Warn when playing back version 0 files which are no longer fully supported and fall back to default pose. Playback of version 1 files should work as expected. --- libraries/avatars/src/AvatarData.cpp | 47 +++++++++++++++++++++------- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 16e4bd5437..2fa26a5f64 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -1270,6 +1270,10 @@ static const QString JSON_AVATAR_DISPLAY_NAME = QStringLiteral("displayName"); static const QString JSON_AVATAR_ATTACHEMENTS = QStringLiteral("attachments"); static const QString JSON_AVATAR_ENTITIES = QStringLiteral("attachedEntities"); static const QString JSON_AVATAR_SCALE = QStringLiteral("scale"); +static const QString JSON_AVATAR_VERSION = QStringLiteral("version"); + +static const int JSON_AVATAR_JOINT_ROTATIONS_IN_RELATIVE_FRAME_VERSION = 0; +static const int JSON_AVATAR_JOINT_ROTATIONS_IN_ABSOLUTE_FRAME_VERSION = 1; QJsonValue toJsonValue(const JointData& joint) { QJsonArray result; @@ -1293,6 +1297,8 @@ JointData jointDataFromJsonValue(const QJsonValue& json) { QJsonObject AvatarData::toJson() const { QJsonObject root; + root[JSON_AVATAR_VERSION] = JSON_AVATAR_JOINT_ROTATIONS_IN_ABSOLUTE_FRAME_VERSION; + if (!getSkeletonModelURL().isEmpty()) { root[JSON_AVATAR_BODY_MODEL] = getSkeletonModelURL().toString(); } @@ -1359,6 +1365,15 @@ QJsonObject AvatarData::toJson() const { } void AvatarData::fromJson(const QJsonObject& json) { + + int version; + if (json.contains(JSON_AVATAR_VERSION)) { + version = json[JSON_AVATAR_VERSION].toInt(); + } else { + // initial data did not have a version field. + version = JSON_AVATAR_JOINT_ROTATIONS_IN_RELATIVE_FRAME_VERSION; + } + // The head setOrientation likes to overwrite the avatar orientation, // so lets do the head first // Most head data is relative to the avatar, and needs no basis correction, @@ -1424,20 +1439,28 @@ void AvatarData::fromJson(const QJsonObject& json) { // } // } - // Joint rotations are relative to the avatar, so they require no basis correction if (json.contains(JSON_AVATAR_JOINT_ARRAY)) { - QVector jointArray; - QJsonArray jointArrayJson = json[JSON_AVATAR_JOINT_ARRAY].toArray(); - jointArray.reserve(jointArrayJson.size()); - int i = 0; - for (const auto& jointJson : jointArrayJson) { - auto joint = jointDataFromJsonValue(jointJson); - jointArray.push_back(joint); - setJointData(i, joint.rotation, joint.translation); - _jointData[i].rotationSet = true; // Have to do that to broadcast the avatar new pose - i++; + if (version == JSON_AVATAR_JOINT_ROTATIONS_IN_RELATIVE_FRAME_VERSION) { + // because we don't have the full joint hierarchy skeleton of the model, + // we can't properly convert from relative rotations into absolute rotations. + quint64 now = usecTimestampNow(); + if (shouldLogError(now)) { + qCWarning(avatars) << "Version 0 avatar recordings not supported. using default rotations"; + } + } else { + QVector jointArray; + QJsonArray jointArrayJson = json[JSON_AVATAR_JOINT_ARRAY].toArray(); + jointArray.reserve(jointArrayJson.size()); + int i = 0; + for (const auto& jointJson : jointArrayJson) { + auto joint = jointDataFromJsonValue(jointJson); + jointArray.push_back(joint); + setJointData(i, joint.rotation, joint.translation); + _jointData[i].rotationSet = true; // Have to do that to broadcast the avatar new pose + i++; + } + setRawJointData(jointArray); } - setRawJointData(jointArray); } } From 3a5d5aab0175667cd48901f5a80e3bdb25fc2f30 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 3 Jun 2016 14:33:50 -0700 Subject: [PATCH 4/5] Removed innocuous "AvatarData packet size mismatch" warning This should not have been a warning, it is expected behavior when a BulkAvatarData packet is filled with data from more then one avatar. --- libraries/avatars/src/AvatarData.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 16e4bd5437..283177c93c 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -632,13 +632,6 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { #endif int numBytesRead = sourceBuffer - startPosition; - - if (numBytesRead != buffer.size()) { - if (shouldLogError(now)) { - qCWarning(avatars) << "AvatarData packet size mismatch: expected " << numBytesRead << " received " << buffer.size(); - } - } - _averageBytesReceived.updateAverage(numBytesRead); return numBytesRead; } From bc81f00dc76e45a29f79800a5949a5fe7c0515ca Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sat, 4 Jun 2016 20:47:10 -0700 Subject: [PATCH 5/5] Eliminate extraneous writes for unchanged values --- libraries/shared/src/SettingHandle.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libraries/shared/src/SettingHandle.cpp b/libraries/shared/src/SettingHandle.cpp index cad2a0286f..b2f23f5a04 100644 --- a/libraries/shared/src/SettingHandle.cpp +++ b/libraries/shared/src/SettingHandle.cpp @@ -28,7 +28,9 @@ Settings::~Settings() { } void Settings::remove(const QString& key) { - _manager->remove(key); + if (key == "" || _manager->contains(key)) { + _manager->remove(key); + } } QStringList Settings::childGroups() const { @@ -72,7 +74,9 @@ void Settings::endGroup() { } void Settings::setValue(const QString& name, const QVariant& value) { - _manager->setValue(name, value); + if (_manager->value(name) != value) { + _manager->setValue(name, value); + } } QVariant Settings::value(const QString& name, const QVariant& defaultValue) const {