namechanges and comments to help clarify necessary fixes

This commit is contained in:
Andrew Meadows 2018-12-12 18:52:26 -08:00
parent 9f404ef006
commit cbcd70aee6
5 changed files with 90 additions and 70 deletions

View file

@ -1321,22 +1321,22 @@ void MyAvatar::saveAvatarEntityDataToSettings() {
for (const auto& id : _entitiesToRemoveFromSettings) { for (const auto& id : _entitiesToRemoveFromSettings) {
// remove // remove
entitiesToSave.erase(id); entitiesToSave.erase(id);
std::map<QUuid, QByteArray>::iterator itr = _poorlyFormattedAvatarEntityData.find(id); std::map<QUuid, QByteArray>::iterator itr = _cachedAvatarEntityDataSettings.find(id);
if (itr != _poorlyFormattedAvatarEntityData.end()) { if (itr != _cachedAvatarEntityDataSettings.end()) {
_poorlyFormattedAvatarEntityData.erase(itr); _cachedAvatarEntityDataSettings.erase(itr);
} }
} }
for (const auto& id : entitiesToSave) { for (const auto& id : entitiesToSave) {
// remove old strings to be replaced by new saves // remove old strings to be replaced by new saves
std::map<QUuid, QByteArray>::iterator itr = _poorlyFormattedAvatarEntityData.find(id); std::map<QUuid, QByteArray>::iterator itr = _cachedAvatarEntityDataSettings.find(id);
if (itr != _poorlyFormattedAvatarEntityData.end()) { if (itr != _cachedAvatarEntityDataSettings.end()) {
_poorlyFormattedAvatarEntityData.erase(itr); _cachedAvatarEntityDataSettings.erase(itr);
} }
} }
_entitiesToRemoveFromSettings.clear(); _entitiesToRemoveFromSettings.clear();
}); });
uint32_t numEntities = (uint32_t)(entitiesToSave.size() + _poorlyFormattedAvatarEntityData.size()); uint32_t numEntities = (uint32_t)(entitiesToSave.size() + _cachedAvatarEntityDataSettings.size());
uint32_t prevNumEntities = _avatarEntityCountSetting.get(0); uint32_t prevNumEntities = _avatarEntityCountSetting.get(0);
resizeAvatarEntitySettingHandles(std::max<uint32_t>(numEntities, prevNumEntities)); resizeAvatarEntitySettingHandles(std::max<uint32_t>(numEntities, prevNumEntities));
@ -1353,11 +1353,11 @@ void MyAvatar::saveAvatarEntityDataToSettings() {
} }
} }
}); });
// convert properties to strings // convert properties to our unfortunately-formatted-binary-blob format
QScriptEngine scriptEngine; QScriptEngine scriptEngine;
QScriptValue toStringMethod = scriptEngine.evaluate("(function() { return JSON.stringify(this) })"); QScriptValue toStringMethod = scriptEngine.evaluate("(function() { return JSON.stringify(this) })");
for (const auto& entry : allProperties) { for (const auto& entry : allProperties) {
// begin recipe our unfortunate legacy avatarEntityData format // begin recipe for converting to our unfortunately-formatted-binar-blob
QScriptValue scriptValue = EntityItemNonDefaultPropertiesToScriptValue(&scriptEngine, entry.second); QScriptValue scriptValue = EntityItemNonDefaultPropertiesToScriptValue(&scriptEngine, entry.second);
QVariant variantProperties = scriptValue.toVariant(); QVariant variantProperties = scriptValue.toVariant();
QJsonDocument jsonProperties = QJsonDocument::fromVariant(variantProperties); QJsonDocument jsonProperties = QJsonDocument::fromVariant(variantProperties);
@ -1372,11 +1372,12 @@ void MyAvatar::saveAvatarEntityDataToSettings() {
QByteArray binaryProperties = jsonProperties.toBinaryData(); QByteArray binaryProperties = jsonProperties.toBinaryData();
// end recipe // end recipe
_poorlyFormattedAvatarEntityData[entry.first] = binaryProperties; // remember this unfortunately-formatted-binary-blob for later so we don't have go through this again
_cachedAvatarEntityDataSettings[entry.first] = binaryProperties;
} }
// save all strings // save all unfortunately-formatted-binary-blobs to settings
uint32_t i = 0; uint32_t i = 0;
for (const auto& entry : _poorlyFormattedAvatarEntityData) { for (const auto& entry : _cachedAvatarEntityDataSettings) {
_avatarEntityIDSettings[i].set(entry.first); _avatarEntityIDSettings[i].set(entry.first);
_avatarEntityDataSettings[i].set(entry.second); _avatarEntityDataSettings[i].set(entry.second);
++i; ++i;
@ -1570,7 +1571,7 @@ void MyAvatar::loadData() {
void MyAvatar::loadAvatarEntityDataFromSettings() { void MyAvatar::loadAvatarEntityDataFromSettings() {
_avatarEntitiesLock.withReadLock([&] { _avatarEntitiesLock.withReadLock([&] {
_avatarEntityData.clear(); _packedAvatarEntityData.clear();
}); });
_reloadAvatarEntityDataFromSettings = false; _reloadAvatarEntityDataFromSettings = false;
@ -1580,32 +1581,34 @@ void MyAvatar::loadAvatarEntityDataFromSettings() {
} }
QScriptEngine scriptEngine; QScriptEngine scriptEngine;
std::vector<EntityItemProperties> entitiesToLoad; std::vector< std::pair<QUuid, EntityItemProperties> > entitiesToLoad;
resizeAvatarEntitySettingHandles(numEntities); resizeAvatarEntitySettingHandles(numEntities);
for (int i = 0; i < numEntities; i++) { for (int i = 0; i < numEntities; i++) {
QUuid entityID = QUuid::createUuid(); // generate a new ID QUuid id = QUuid::createUuid(); // generate a new ID
QByteArray binaryData = _avatarEntityDataSettings[i].get();
//updateAvatarEntity(entityID, binaryData);
// the avatarEntityData is stored as an unfortunately-formatted-binary-blob
QByteArray binaryData = _avatarEntityDataSettings[i].get();
_avatarEntityDataChanged = true; _avatarEntityDataChanged = true;
if (_clientTraitsHandler) { if (_clientTraitsHandler) {
// we have a client traits handler, so we need to mark this instanced trait as changed // we have a client traits handler, so we need to mark this instanced trait as changed
// so that changes will be sent next frame // so that changes will be sent next frame
_clientTraitsHandler->markInstancedTraitUpdated(AvatarTraits::AvatarEntity, entityID); _clientTraitsHandler->markInstancedTraitUpdated(AvatarTraits::AvatarEntity, id);
} }
// begin recipe to extract EntityItemProperties from unfortunately-formatted-binary-blob
QJsonDocument jsonProperties = QJsonDocument::fromBinaryData(binaryData); QJsonDocument jsonProperties = QJsonDocument::fromBinaryData(binaryData);
if (!jsonProperties.isObject()) { if (!jsonProperties.isObject()) {
qCDebug(interfaceapp) << "bad avatarEntityData json" << QString(binaryData.toHex()); qCDebug(interfaceapp) << "bad avatarEntityData json" << QString(binaryData.toHex());
continue; continue;
} }
QVariant variant = jsonProperties.toVariant();
QVariant variantProperties = jsonProperties.toVariant(); QVariantMap variantMap = variant.toMap();
QVariantMap asMap = variantProperties.toMap(); QScriptValue scriptValue = variantMapToScriptValue(variantMap, scriptEngine);
QScriptValue scriptProperties = variantMapToScriptValue(asMap, scriptEngine);
EntityItemProperties properties; EntityItemProperties properties;
EntityItemPropertiesFromScriptValueHonorReadOnly(scriptProperties, properties); EntityItemPropertiesFromScriptValueHonorReadOnly(scriptValue, properties);
// end recipe
properties.setEntityHostType(entity::HostType::AVATAR); properties.setEntityHostType(entity::HostType::AVATAR);
properties.setOwningAvatarID(getID()); properties.setOwningAvatarID(getID());
@ -1624,36 +1627,38 @@ void MyAvatar::loadAvatarEntityDataFromSettings() {
// and seems safe (per Seth). // and seems safe (per Seth).
properties.markAllChanged(); properties.markAllChanged();
entitiesToLoad.push_back(properties); entitiesToLoad.push_back({id, properties});
} }
_poorlyFormattedAvatarEntityData.clear(); _cachedAvatarEntityDataSettings.clear();
auto entityTreeRenderer = qApp->getEntities(); auto entityTreeRenderer = qApp->getEntities();
EntityTreePointer entityTree = entityTreeRenderer ? entityTreeRenderer->getTree() : nullptr; EntityTreePointer entityTree = entityTreeRenderer ? entityTreeRenderer->getTree() : nullptr;
if (entityTree) { if (entityTree) {
OctreePacketData packetData(false, AvatarTraits::MAXIMUM_TRAIT_SIZE); OctreePacketData packetData(false, AvatarTraits::MAXIMUM_TRAIT_SIZE);
EncodeBitstreamParams params; EncodeBitstreamParams params;
EntityTreeElementExtraEncodeDataPointer extra { nullptr }; EntityTreeElementExtraEncodeDataPointer extra { nullptr };
for (uint32_t i = 0; i < entitiesToLoad.size(); ++i) { uint32_t i = 0;
for (const auto& entry : entitiesToLoad) {
// try to create the entity // try to create the entity
QUuid entityID = QUuid::createUuid(); // generate a new ID
entityTree->withWriteLock([&] { entityTree->withWriteLock([&] {
EntityItemPointer entity = entityTree->addEntity(entityID, entitiesToLoad[i]); QUuid id = entry.first;
EntityItemPointer entity = entityTree->addEntity(id, entry.second);
if (entity) { if (entity) {
// use the entity to build the data payload // use the entity to build the data payload
OctreeElement::AppendState appendState = entity->appendEntityData(&packetData, params, extra); OctreeElement::AppendState appendState = entity->appendEntityData(&packetData, params, extra);
if (appendState == OctreeElement::COMPLETED) { if (appendState == OctreeElement::COMPLETED) {
// only remember an AvatarEntity that successfully loads and can be packed // only remember an AvatarEntity that successfully loads and can be packed
QByteArray tempArray((const char*)packetData.getUncompressedData(), packetData.getUncompressedSize()); QByteArray tempArray((const char*)packetData.getUncompressedData(), packetData.getUncompressedSize());
storeAvatarEntityDataPayload(entityID, tempArray); storeAvatarEntityDataPayload(id, tempArray);
// we store these binaryProperties for later: when saving back to settings // only cache things that successfully loaded and packed
// unfortunately we must use this non-human-readable format because reasons // we cache these binaryProperties for later: for when saving back to settings
_poorlyFormattedAvatarEntityData[entityID] = _avatarEntityDataSettings[i].get(); _cachedAvatarEntityDataSettings[id] = _avatarEntityDataSettings[i].get();
} }
packetData.reset(); packetData.reset();
} }
}); });
++i;
} }
} else { } else {
// TODO? handle this case: try to load AvatatEntityData from settings again later? // TODO? handle this case: try to load AvatatEntityData from settings again later?

View file

@ -1948,7 +1948,7 @@ private:
Setting::Handle<bool> _allowTeleportingSetting { "allowTeleporting", true }; Setting::Handle<bool> _allowTeleportingSetting { "allowTeleporting", true };
std::vector<Setting::Handle<QUuid>> _avatarEntityIDSettings; std::vector<Setting::Handle<QUuid>> _avatarEntityIDSettings;
std::vector<Setting::Handle<QByteArray>> _avatarEntityDataSettings; std::vector<Setting::Handle<QByteArray>> _avatarEntityDataSettings;
std::map<QUuid, QByteArray> _poorlyFormattedAvatarEntityData; std::map<QUuid, QByteArray> _cachedAvatarEntityDataSettings;
std::set<QUuid> _entitiesToSaveToSettings; std::set<QUuid> _entitiesToSaveToSettings;
std::set<QUuid> _entitiesToRemoveFromSettings; std::set<QUuid> _entitiesToRemoveFromSettings;
}; };

View file

@ -436,12 +436,12 @@ void Avatar::updateAvatarEntities() {
AvatarEntityIDs recentlyDetachedAvatarEntities = getAndClearRecentlyDetachedIDs(); AvatarEntityIDs recentlyDetachedAvatarEntities = getAndClearRecentlyDetachedIDs();
if (!recentlyDetachedAvatarEntities.empty()) { if (!recentlyDetachedAvatarEntities.empty()) {
// only lock this thread when absolutely necessary // only lock this thread when absolutely necessary
AvatarEntityMap avatarEntityData; AvatarEntityMap packedAvatarEntityData;
_avatarEntitiesLock.withReadLock([&] { _avatarEntitiesLock.withReadLock([&] {
avatarEntityData = _avatarEntityData; packedAvatarEntityData = _packedAvatarEntityData;
}); });
foreach (auto entityID, recentlyDetachedAvatarEntities) { foreach (auto entityID, recentlyDetachedAvatarEntities) {
if (!avatarEntityData.contains(entityID)) { if (!packedAvatarEntityData.contains(entityID)) {
entityTree->deleteEntity(entityID, true, true); entityTree->deleteEntity(entityID, true, true);
} }
} }

View file

@ -1908,10 +1908,9 @@ qint64 AvatarData::packAvatarEntityTraitInstance(AvatarTraits::TraitType traitTy
// grab a read lock on the avatar entities and check for entity data for the given ID // grab a read lock on the avatar entities and check for entity data for the given ID
QByteArray entityBinaryData; QByteArray entityBinaryData;
_avatarEntitiesLock.withReadLock([this, &entityBinaryData, &traitInstanceID] { _avatarEntitiesLock.withReadLock([this, &entityBinaryData, &traitInstanceID] {
if (_avatarEntityData.contains(traitInstanceID)) { if (_packedAvatarEntityData.contains(traitInstanceID)) {
entityBinaryData = _avatarEntityData[traitInstanceID]; entityBinaryData = _packedAvatarEntityData[traitInstanceID];
} }
}); });
@ -1998,7 +1997,7 @@ qint64 AvatarData::packTraitInstance(AvatarTraits::TraitType traitType, AvatarTr
void AvatarData::prepareResetTraitInstances() { void AvatarData::prepareResetTraitInstances() {
if (_clientTraitsHandler) { if (_clientTraitsHandler) {
_avatarEntitiesLock.withReadLock([this]{ _avatarEntitiesLock.withReadLock([this]{
foreach (auto entityID, _avatarEntityData.keys()) { foreach (auto entityID, _packedAvatarEntityData.keys()) {
_clientTraitsHandler->markInstancedTraitUpdated(AvatarTraits::AvatarEntity, entityID); _clientTraitsHandler->markInstancedTraitUpdated(AvatarTraits::AvatarEntity, entityID);
} }
foreach (auto grabID, _avatarGrabData.keys()) { foreach (auto grabID, _avatarGrabData.keys()) {
@ -2367,7 +2366,7 @@ void AvatarData::setRecordingBasis(std::shared_ptr<Transform> recordingBasis) {
void AvatarData::createRecordingIDs() { void AvatarData::createRecordingIDs() {
_avatarEntitiesLock.withReadLock([&] { _avatarEntitiesLock.withReadLock([&] {
_avatarEntityForRecording.clear(); _avatarEntityForRecording.clear();
for (int i = 0; i < _avatarEntityData.size(); i++) { for (int i = 0; i < _packedAvatarEntityData.size(); i++) {
_avatarEntityForRecording.insert(QUuid::createUuid()); _avatarEntityForRecording.insert(QUuid::createUuid());
} }
}); });
@ -2422,6 +2421,25 @@ JointData jointDataFromJsonValue(int version, const QJsonValue& json) {
return result; return result;
} }
void AvatarData::avatarEntityDataToJson(QJsonObject& root) const {
// ADEBUG this is broken
_avatarEntitiesLock.withReadLock([&] {
AvatarEntityMap _avatarEntityData = _packedAvatarEntityData; // hack to compile
if (!_avatarEntityData.empty()) {
QJsonArray avatarEntityJson;
int entityCount = 0;
for (auto entityID : _avatarEntityData.keys()) {
QVariantMap entityData;
QUuid newId = _avatarEntityForRecording.size() == _avatarEntityData.size() ? _avatarEntityForRecording.values()[entityCount++] : entityID;
entityData.insert("id", newId);
entityData.insert("properties", _avatarEntityData.value(entityID).toBase64());
avatarEntityJson.push_back(QVariant(entityData).toJsonObject());
}
root[JSON_AVATAR_ENTITIES] = avatarEntityJson;
}
});
}
QJsonObject AvatarData::toJson() const { QJsonObject AvatarData::toJson() const {
QJsonObject root; QJsonObject root;
@ -2433,20 +2451,8 @@ QJsonObject AvatarData::toJson() const {
if (!getDisplayName().isEmpty()) { if (!getDisplayName().isEmpty()) {
root[JSON_AVATAR_DISPLAY_NAME] = getDisplayName(); root[JSON_AVATAR_DISPLAY_NAME] = getDisplayName();
} }
_avatarEntitiesLock.withReadLock([&] {
if (!_avatarEntityData.empty()) { avatarEntityDataToJson(root);
QJsonArray avatarEntityJson;
int entityCount = 0;
for (auto entityID : _avatarEntityData.keys()) {
QVariantMap entityData;
QUuid newId = _avatarEntityForRecording.size() == _avatarEntityData.size() ? _avatarEntityForRecording.values()[entityCount++] : entityID;
entityData.insert("id", newId);
entityData.insert("properties", _avatarEntityData.value(entityID).toBase64());
avatarEntityJson.push_back(QVariant(entityData).toJsonObject());
}
root[JSON_AVATAR_ENTITIES] = avatarEntityJson;
}
});
auto recordingBasis = getRecordingBasis(); auto recordingBasis = getRecordingBasis();
bool success; bool success;
@ -2568,10 +2574,10 @@ void AvatarData::fromJson(const QJsonObject& json, bool useFrameSkeleton) {
for (auto attachmentJson : attachmentsJson) { for (auto attachmentJson : attachmentsJson) {
if (attachmentJson.isObject()) { if (attachmentJson.isObject()) {
QVariantMap entityData = attachmentJson.toObject().toVariantMap(); QVariantMap entityData = attachmentJson.toObject().toVariantMap();
QUuid entityID = entityData.value("id").toUuid(); QUuid id = entityData.value("id").toUuid();
// ADEBUG TODO: fix this broken path // ADEBUG TODO: fix this broken path
QByteArray properties = QByteArray::fromBase64(entityData.value("properties").toByteArray()); QByteArray data = QByteArray::fromBase64(entityData.value("properties").toByteArray());
storeAvatarEntityDataPayload(entityID, properties); updateAvatarEntityData(id, data);
} }
} }
} }
@ -2757,10 +2763,10 @@ const int MAX_NUM_AVATAR_ENTITIES = 42;
void AvatarData::storeAvatarEntityDataPayload(const QUuid& entityID, const QByteArray& data) { void AvatarData::storeAvatarEntityDataPayload(const QUuid& entityID, const QByteArray& data) {
_avatarEntitiesLock.withWriteLock([&] { _avatarEntitiesLock.withWriteLock([&] {
AvatarEntityMap::iterator itr = _avatarEntityData.find(entityID); PackedAvatarEntityMap::iterator itr = _packedAvatarEntityData.find(entityID);
if (itr == _avatarEntityData.end()) { if (itr == _packedAvatarEntityData.end()) {
if (_avatarEntityData.size() < MAX_NUM_AVATAR_ENTITIES) { if (_packedAvatarEntityData.size() < MAX_NUM_AVATAR_ENTITIES) {
_avatarEntityData.insert(entityID, data); _packedAvatarEntityData.insert(entityID, data);
} }
} else { } else {
itr.value() = data; itr.value() = data;
@ -2776,8 +2782,12 @@ void AvatarData::storeAvatarEntityDataPayload(const QUuid& entityID, const QByte
} }
} }
void AvatarData::updateAvatarEntity(const QUuid& id, const QScriptValue& data) { void AvatarData::updateAvatarEntity(const QUuid& id, const QScriptValue& scriptValue) {
// no op // overridden where needed
}
void AvatarData::updateAvatarEntityData(const QUuid& id, const QByteArray& data) {
// ADEBUG TODO: implement this
} }
void AvatarData::clearAvatarEntity(const QUuid& entityID, bool requiresRemovalFromTree) { void AvatarData::clearAvatarEntity(const QUuid& entityID, bool requiresRemovalFromTree) {
@ -2785,7 +2795,7 @@ void AvatarData::clearAvatarEntity(const QUuid& entityID, bool requiresRemovalFr
bool removedEntity = false; bool removedEntity = false;
_avatarEntitiesLock.withWriteLock([this, &removedEntity, &entityID] { _avatarEntitiesLock.withWriteLock([this, &removedEntity, &entityID] {
removedEntity = _avatarEntityData.remove(entityID); removedEntity = _packedAvatarEntityData.remove(entityID);
}); });
insertDetachedEntityID(entityID); insertDetachedEntityID(entityID);
@ -2798,9 +2808,10 @@ void AvatarData::clearAvatarEntity(const QUuid& entityID, bool requiresRemovalFr
} }
AvatarEntityMap AvatarData::getAvatarEntityData() const { AvatarEntityMap AvatarData::getAvatarEntityData() const {
// ADEBUG broken
AvatarEntityMap result; AvatarEntityMap result;
_avatarEntitiesLock.withReadLock([&] { _avatarEntitiesLock.withReadLock([&] {
result = _avatarEntityData; result = _packedAvatarEntityData;
}); });
return result; return result;
} }
@ -2823,7 +2834,9 @@ void AvatarData::setAvatarEntityData(const AvatarEntityMap& avatarEntityData) {
std::vector<QUuid> deletedEntityIDs; std::vector<QUuid> deletedEntityIDs;
QList<QUuid> updatedEntityIDs; QList<QUuid> updatedEntityIDs;
// ADEBUG this is broken
_avatarEntitiesLock.withWriteLock([&] { _avatarEntitiesLock.withWriteLock([&] {
AvatarEntityMap _avatarEntityData = _packedAvatarEntityData; // hack to compile
if (_avatarEntityData != avatarEntityData) { if (_avatarEntityData != avatarEntityData) {
// keep track of entities that were attached to this avatar but no longer are // keep track of entities that were attached to this avatar but no longer are

View file

@ -63,6 +63,7 @@ using AvatarWeakPointer = std::weak_ptr<AvatarData>;
using AvatarHash = QHash<QUuid, AvatarSharedPointer>; using AvatarHash = QHash<QUuid, AvatarSharedPointer>;
using AvatarEntityMap = QMap<QUuid, QByteArray>; using AvatarEntityMap = QMap<QUuid, QByteArray>;
using PackedAvatarEntityMap = QMap<QUuid, QByteArray>; // similar to AvatarEntityMap, but different internal format
using AvatarEntityIDs = QSet<QUuid>; using AvatarEntityIDs = QSet<QUuid>;
using AvatarGrabDataMap = QMap<QUuid, QByteArray>; using AvatarGrabDataMap = QMap<QUuid, QByteArray>;
@ -959,7 +960,8 @@ public:
* @param {Uuid} entityID * @param {Uuid} entityID
* @param {object} entityData * @param {object} entityData
*/ */
Q_INVOKABLE virtual void updateAvatarEntity(const QUuid& id, const QScriptValue& data); Q_INVOKABLE virtual void updateAvatarEntity(const QUuid& id, const QScriptValue& scriptValue);
virtual void updateAvatarEntityData(const QUuid& id, const QByteArray& data);
/**jsdoc /**jsdoc
* @function MyAvatar.clearAvatarEntity * @function MyAvatar.clearAvatarEntity
@ -1126,6 +1128,7 @@ public:
TransformPointer getRecordingBasis() const; TransformPointer getRecordingBasis() const;
void setRecordingBasis(TransformPointer recordingBasis = TransformPointer()); void setRecordingBasis(TransformPointer recordingBasis = TransformPointer());
void createRecordingIDs(); void createRecordingIDs();
void avatarEntityDataToJson(QJsonObject& root) const;
QJsonObject toJson() const; QJsonObject toJson() const;
void fromJson(const QJsonObject& json, bool useFrameSkeleton = true); void fromJson(const QJsonObject& json, bool useFrameSkeleton = true);
@ -1140,11 +1143,10 @@ public:
Q_INVOKABLE AvatarEntityMap getAvatarEntityData() const; Q_INVOKABLE AvatarEntityMap getAvatarEntityData() const;
/**jsdoc /**jsdoc
* Temporarily disabled. Use updateAvatarEntity(id, properties) in the meantime.
* @function MyAvatar.setAvatarEntityData * @function MyAvatar.setAvatarEntityData
* @param {object} avatarEntityData * @param {object} avatarEntityData
*/ */
void setAvatarEntityData(const AvatarEntityMap& avatarEntityData); Q_INVOKABLE void setAvatarEntityData(const AvatarEntityMap& avatarEntityData);
virtual void setAvatarEntityDataChanged(bool value) { _avatarEntityDataChanged = value; } virtual void setAvatarEntityDataChanged(bool value) { _avatarEntityDataChanged = value; }
void insertDetachedEntityID(const QUuid entityID); void insertDetachedEntityID(const QUuid entityID);
@ -1465,7 +1467,7 @@ protected:
mutable ReadWriteLockable _avatarEntitiesLock; mutable ReadWriteLockable _avatarEntitiesLock;
AvatarEntityIDs _avatarEntityDetached; // recently detached from this avatar AvatarEntityIDs _avatarEntityDetached; // recently detached from this avatar
AvatarEntityIDs _avatarEntityForRecording; // create new entities id for avatar recording AvatarEntityIDs _avatarEntityForRecording; // create new entities id for avatar recording
AvatarEntityMap _avatarEntityData; PackedAvatarEntityMap _packedAvatarEntityData;
bool _avatarEntityDataChanged { false }; bool _avatarEntityDataChanged { false };
mutable ReadWriteLockable _avatarGrabsLock; mutable ReadWriteLockable _avatarGrabsLock;