mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
Merge pull request #8041 from sethalves/fix-avatar-entity-locking
Fix avatar entity locking
This commit is contained in:
commit
b14f9cd312
4 changed files with 65 additions and 39 deletions
|
@ -239,11 +239,13 @@ void Avatar::updateAvatarEntities() {
|
|||
}
|
||||
|
||||
AvatarEntityIDs recentlyDettachedAvatarEntities = getAndClearRecentlyDetachedIDs();
|
||||
foreach (auto entityID, recentlyDettachedAvatarEntities) {
|
||||
if (!_avatarEntityData.contains(entityID)) {
|
||||
entityTree->deleteEntity(entityID, true, true);
|
||||
_avatarEntitiesLock.withReadLock([&] {
|
||||
foreach (auto entityID, recentlyDettachedAvatarEntities) {
|
||||
if (!_avatarEntityData.contains(entityID)) {
|
||||
entityTree->deleteEntity(entityID, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (success) {
|
||||
|
|
|
@ -709,12 +709,14 @@ void MyAvatar::saveData() {
|
|||
|
||||
settings.beginWriteArray("avatarEntityData");
|
||||
int avatarEntityIndex = 0;
|
||||
for (auto entityID : _avatarEntityData.keys()) {
|
||||
settings.setArrayIndex(avatarEntityIndex);
|
||||
settings.setValue("id", entityID);
|
||||
settings.setValue("properties", _avatarEntityData.value(entityID));
|
||||
avatarEntityIndex++;
|
||||
}
|
||||
_avatarEntitiesLock.withReadLock([&] {
|
||||
for (auto entityID : _avatarEntityData.keys()) {
|
||||
settings.setArrayIndex(avatarEntityIndex);
|
||||
settings.setValue("id", entityID);
|
||||
settings.setValue("properties", _avatarEntityData.value(entityID));
|
||||
avatarEntityIndex++;
|
||||
}
|
||||
});
|
||||
settings.endArray();
|
||||
|
||||
settings.setValue("displayName", _displayName);
|
||||
|
|
|
@ -900,7 +900,11 @@ bool AvatarData::processAvatarIdentity(const Identity& identity) {
|
|||
hasIdentityChanged = true;
|
||||
}
|
||||
|
||||
if (identity.avatarEntityData != _avatarEntityData) {
|
||||
bool avatarEntityDataChanged = false;
|
||||
_avatarEntitiesLock.withReadLock([&] {
|
||||
avatarEntityDataChanged = (identity.avatarEntityData != _avatarEntityData);
|
||||
});
|
||||
if (avatarEntityDataChanged) {
|
||||
setAvatarEntityData(identity.avatarEntityData);
|
||||
hasIdentityChanged = true;
|
||||
}
|
||||
|
@ -914,7 +918,9 @@ QByteArray AvatarData::identityByteArray() {
|
|||
QUrl emptyURL("");
|
||||
const QUrl& urlToSend = _skeletonModelURL.scheme() == "file" ? emptyURL : _skeletonModelURL;
|
||||
|
||||
identityStream << getSessionUUID() << urlToSend << _attachmentData << _displayName << _avatarEntityData;
|
||||
_avatarEntitiesLock.withReadLock([&] {
|
||||
identityStream << getSessionUUID() << urlToSend << _attachmentData << _displayName << _avatarEntityData;
|
||||
});
|
||||
|
||||
return identityData;
|
||||
}
|
||||
|
@ -1306,16 +1312,18 @@ QJsonObject AvatarData::toJson() const {
|
|||
root[JSON_AVATAR_ATTACHEMENTS] = attachmentsJson;
|
||||
}
|
||||
|
||||
if (!_avatarEntityData.empty()) {
|
||||
QJsonArray avatarEntityJson;
|
||||
for (auto entityID : _avatarEntityData.keys()) {
|
||||
QVariantMap entityData;
|
||||
entityData.insert("id", entityID);
|
||||
entityData.insert("properties", _avatarEntityData.value(entityID));
|
||||
avatarEntityJson.push_back(QVariant(entityData).toJsonObject());
|
||||
_avatarEntitiesLock.withReadLock([&] {
|
||||
if (!_avatarEntityData.empty()) {
|
||||
QJsonArray avatarEntityJson;
|
||||
for (auto entityID : _avatarEntityData.keys()) {
|
||||
QVariantMap entityData;
|
||||
entityData.insert("id", entityID);
|
||||
entityData.insert("properties", _avatarEntityData.value(entityID));
|
||||
avatarEntityJson.push_back(QVariant(entityData).toJsonObject());
|
||||
}
|
||||
root[JSON_AVATAR_ENTITIES] = avatarEntityJson;
|
||||
}
|
||||
root[JSON_AVATAR_ENTITIES] = avatarEntityJson;
|
||||
}
|
||||
});
|
||||
|
||||
auto recordingBasis = getRecordingBasis();
|
||||
bool success;
|
||||
|
@ -1604,8 +1612,10 @@ void AvatarData::updateAvatarEntity(const QUuid& entityID, const QByteArray& ent
|
|||
QMetaObject::invokeMethod(this, "updateAvatarEntity", Q_ARG(const QUuid&, entityID), Q_ARG(QByteArray, entityData));
|
||||
return;
|
||||
}
|
||||
_avatarEntityData.insert(entityID, entityData);
|
||||
_avatarEntityDataLocallyEdited = true;
|
||||
_avatarEntitiesLock.withWriteLock([&] {
|
||||
_avatarEntityData.insert(entityID, entityData);
|
||||
_avatarEntityDataLocallyEdited = true;
|
||||
});
|
||||
}
|
||||
|
||||
void AvatarData::clearAvatarEntity(const QUuid& entityID) {
|
||||
|
@ -1613,18 +1623,25 @@ void AvatarData::clearAvatarEntity(const QUuid& entityID) {
|
|||
QMetaObject::invokeMethod(this, "clearAvatarEntity", Q_ARG(const QUuid&, entityID));
|
||||
return;
|
||||
}
|
||||
_avatarEntityData.remove(entityID);
|
||||
_avatarEntityDataLocallyEdited = true;
|
||||
|
||||
_avatarEntitiesLock.withWriteLock([&] {
|
||||
_avatarEntityData.remove(entityID);
|
||||
_avatarEntityDataLocallyEdited = true;
|
||||
});
|
||||
}
|
||||
|
||||
AvatarEntityMap AvatarData::getAvatarEntityData() const {
|
||||
AvatarEntityMap result;
|
||||
if (QThread::currentThread() != thread()) {
|
||||
AvatarEntityMap result;
|
||||
QMetaObject::invokeMethod(const_cast<AvatarData*>(this), "getAvatarEntityData", Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(AvatarEntityMap, result));
|
||||
return result;
|
||||
}
|
||||
return _avatarEntityData;
|
||||
|
||||
_avatarEntitiesLock.withReadLock([&] {
|
||||
result = _avatarEntityData;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
void AvatarData::setAvatarEntityData(const AvatarEntityMap& avatarEntityData) {
|
||||
|
@ -1632,29 +1649,33 @@ void AvatarData::setAvatarEntityData(const AvatarEntityMap& avatarEntityData) {
|
|||
QMetaObject::invokeMethod(this, "setAvatarEntityData", Q_ARG(const AvatarEntityMap&, avatarEntityData));
|
||||
return;
|
||||
}
|
||||
if (_avatarEntityData != avatarEntityData) {
|
||||
// keep track of entities that were attached to this avatar but no longer are
|
||||
AvatarEntityIDs previousAvatarEntityIDs = QSet<QUuid>::fromList(_avatarEntityData.keys());
|
||||
_avatarEntitiesLock.withWriteLock([&] {
|
||||
if (_avatarEntityData != avatarEntityData) {
|
||||
// keep track of entities that were attached to this avatar but no longer are
|
||||
AvatarEntityIDs previousAvatarEntityIDs = QSet<QUuid>::fromList(_avatarEntityData.keys());
|
||||
|
||||
_avatarEntityData = avatarEntityData;
|
||||
setAvatarEntityDataChanged(true);
|
||||
_avatarEntityData = avatarEntityData;
|
||||
setAvatarEntityDataChanged(true);
|
||||
|
||||
foreach (auto entityID, previousAvatarEntityIDs) {
|
||||
if (!_avatarEntityData.contains(entityID)) {
|
||||
_avatarEntityDetached.insert(entityID);
|
||||
foreach (auto entityID, previousAvatarEntityIDs) {
|
||||
if (!_avatarEntityData.contains(entityID)) {
|
||||
_avatarEntityDetached.insert(entityID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
AvatarEntityIDs AvatarData::getAndClearRecentlyDetachedIDs() {
|
||||
AvatarEntityIDs result;
|
||||
if (QThread::currentThread() != thread()) {
|
||||
AvatarEntityIDs result;
|
||||
QMetaObject::invokeMethod(const_cast<AvatarData*>(this), "getRecentlyDetachedIDs", Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(AvatarEntityIDs, result));
|
||||
return result;
|
||||
}
|
||||
AvatarEntityIDs result = _avatarEntityDetached;
|
||||
_avatarEntityDetached.clear();
|
||||
_avatarEntitiesLock.withWriteLock([&] {
|
||||
result = _avatarEntityDetached;
|
||||
_avatarEntityDetached.clear();
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -418,6 +418,7 @@ protected:
|
|||
// updates about one avatar to another.
|
||||
glm::vec3 _globalPosition;
|
||||
|
||||
mutable ReadWriteLockable _avatarEntitiesLock;
|
||||
AvatarEntityIDs _avatarEntityDetached; // recently detached from this avatar
|
||||
AvatarEntityMap _avatarEntityData;
|
||||
bool _avatarEntityDataLocallyEdited { false };
|
||||
|
|
Loading…
Reference in a new issue