From 01fc4426955e6934476a5a0c7ad4b15dc69df25c Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 4 Dec 2018 18:08:54 -0800 Subject: [PATCH] save AvatarEntities settings as strings --- interface/src/avatar/MyAvatar.cpp | 72 ++++++++++++------- interface/src/avatar/MyAvatar.h | 4 +- .../src/avatars-renderer/Avatar.cpp | 10 +-- .../entities/src/EntityItemProperties.cpp | 10 +++ libraries/entities/src/EntityItemProperties.h | 2 + 5 files changed, 63 insertions(+), 35 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index e40fc7f9dd..0e17fa8fbe 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1263,11 +1263,11 @@ void MyAvatar::resizeAvatarEntitySettingHandles(unsigned int avatarEntityIndex) // Create Setting::Handles to mimic this. while (_avatarEntityIDSettings.size() <= avatarEntityIndex) { - Setting::Handle idHandle(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "avatarEntityData" - << QString::number(avatarEntityIndex + 1) << "id", QUuid()); + Setting::Handle idHandle(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "avatarEntityData" + << QString::number(avatarEntityIndex + 1) << "id", QUuid().toString()); _avatarEntityIDSettings.push_back(idHandle); - Setting::Handle dataHandle(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "avatarEntityData" - << QString::number(avatarEntityIndex + 1) << "properties", QByteArray()); + Setting::Handle dataHandle(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "avatarEntityData" + << QString::number(avatarEntityIndex + 1) << "properties", QString()); _avatarEntityDataSettings.push_back(dataHandle); } } @@ -1299,23 +1299,46 @@ void MyAvatar::saveData() { auto hmdInterface = DependencyManager::get(); _avatarEntitiesLock.withReadLock([&] { - QList avatarEntityIDs = _avatarEntityData.keys(); - unsigned int avatarEntityCount = avatarEntityIDs.size(); - unsigned int previousAvatarEntityCount = _avatarEntityCountSetting.get(0); - resizeAvatarEntitySettingHandles(std::max(avatarEntityCount, previousAvatarEntityCount)); - _avatarEntityCountSetting.set(avatarEntityCount); + uint32_t numEntities = _avatarEntityData.size(); + uint32_t prevNumEntities = _avatarEntityCountSetting.get(0); + resizeAvatarEntitySettingHandles(std::max(numEntities, prevNumEntities)); - unsigned int avatarEntityIndex = 0; - for (auto entityID : avatarEntityIDs) { - _avatarEntityIDSettings[avatarEntityIndex].set(entityID); - _avatarEntityDataSettings[avatarEntityIndex].set(_avatarEntityData.value(entityID)); - avatarEntityIndex++; + // Note: this roundabout path from AvatarEntityData to JSON string is NOT efficient + QScriptEngine engine; + QScriptValue toStringMethod = engine.evaluate("(function() { return JSON.stringify(this) })"); + AvatarEntityMap::const_iterator itr = _avatarEntityData.begin(); + numEntities = 0; + while (itr != _avatarEntityData.end()) { + EntityItemProperties properties; + QByteArray buffer = itr.value(); + if (properties.constructFromBuffer((uint8_t*)buffer.data(), buffer.size())) { + if (properties.getParentID() == getSessionUUID()) { + properties.setParentID(AVATAR_SELF_ID); + } + QScriptValue scriptValue = EntityItemPropertiesToScriptValue(&engine, properties); + scriptValue.setProperty("toString", toStringMethod); + _avatarEntityDataSettings[numEntities].set(scriptValue.toString()); + _avatarEntityIDSettings[numEntities].set(itr.key().toString()); + ++numEntities; + } else { + // buffer is corrupt --> skip it + } + ++itr; } + _avatarEntityCountSetting.set(numEntities); - // clean up any left-over (due to the list shrinking) slots - for (; avatarEntityIndex < previousAvatarEntityCount; avatarEntityIndex++) { - _avatarEntityIDSettings[avatarEntityIndex].remove(); - _avatarEntityDataSettings[avatarEntityIndex].remove(); + if (numEntities < prevNumEntities) { + uint32_t numEntitiesToRemove = prevNumEntities - numEntities; + for (uint32_t i = 0; i < numEntitiesToRemove; ++i) { + if (_avatarEntityIDSettings.size() > numEntities) { + _avatarEntityIDSettings.back().remove(); + _avatarEntityIDSettings.pop_back(); + } + if (_avatarEntityDataSettings.size() > numEntities) { + _avatarEntityDataSettings.back().remove(); + _avatarEntityDataSettings.pop_back(); + } + } } }); } @@ -1426,13 +1449,14 @@ void MyAvatar::loadData() { useFullAvatarURL(_fullAvatarURLFromPreferences, _fullAvatarModelName); - int avatarEntityCount = _avatarEntityCountSetting.get(0); - for (int i = 0; i < avatarEntityCount; i++) { + int numEntities = _avatarEntityCountSetting.get(0); + + for (int i = 0; i < numEntities; i++) { resizeAvatarEntitySettingHandles(i); - // QUuid entityID = QUuid::createUuid(); // generate a new ID - QUuid entityID = _avatarEntityIDSettings[i].get(QUuid()); - QByteArray properties = _avatarEntityDataSettings[i].get(); - updateAvatarEntity(entityID, properties); + QUuid entityID = QUuid::createUuid(); // generate a new ID + QString propertiesString = _avatarEntityDataSettings[i].get(); + // TODO: convert propertiesString to EntityItemProperties + //updateAvatarEntity(entityID, properties); } // Flying preferences must be loaded before calling setFlyingEnabled() diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 17b71153ea..1984ea9766 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -1936,8 +1936,8 @@ private: Setting::Handle _flyingHMDSetting; Setting::Handle _avatarEntityCountSetting; Setting::Handle _allowTeleportingSetting { "allowTeleporting", true }; - std::vector> _avatarEntityIDSettings; - std::vector> _avatarEntityDataSettings; + std::vector> _avatarEntityIDSettings; + std::vector> _avatarEntityDataSettings; }; QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 2c52bc69ea..23093028b1 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -383,15 +383,7 @@ void Avatar::updateAvatarEntities() { // create a temporary EntityItem to unpack the data int32_t bytesLeftToRead = data.size(); unsigned char* dataAt = (unsigned char*)(data.data()); - ReadBitstreamToTreeParams args; - EntityItemPointer tempEntity = EntityTypes::constructEntityItem(dataAt, bytesLeftToRead, args); - if (!tempEntity) { - continue; - } - tempEntity->readEntityDataFromBuffer(dataAt, bytesLeftToRead, args); - - // extract the properties from tempEntity - properties = tempEntity->getProperties(); + properties.constructFromBuffer(dataAt, bytesLeftToRead); } properties.setEntityHostType(entity::HostType::AVATAR); diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 26bb450b2e..0badd00bc3 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -90,6 +90,16 @@ void EntityItemProperties::setLastEdited(quint64 usecTime) { _lastEdited = usecTime > _created ? usecTime : _created; } +bool EntityItemProperties::constructFromBuffer(const unsigned char* data, int dataLength) { + ReadBitstreamToTreeParams args; + EntityItemPointer tempEntity = EntityTypes::constructEntityItem(data, dataLength, args); + if (!tempEntity) { + return false; + } + tempEntity->readEntityDataFromBuffer(data, dataLength, args); + (*this) = tempEntity->getProperties(); + return true; +} QHash stringToShapeTypeLookup; diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 17ec83be78..4a9729f5fe 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -135,6 +135,8 @@ public: EntityPropertyFlags getDesiredProperties() { return _desiredProperties; } void setDesiredProperties(EntityPropertyFlags properties) { _desiredProperties = properties; } + bool constructFromBuffer(const unsigned char* data, int dataLength); + // Note: DEFINE_PROPERTY(PROP_FOO, Foo, foo, type, value) creates the following methods and variables: // type getFoo() const; // void setFoo(type);