diff --git a/interface/src/AvatarBookmarks.cpp b/interface/src/AvatarBookmarks.cpp index 4e3e539dea..3e0e643bd8 100644 --- a/interface/src/AvatarBookmarks.cpp +++ b/interface/src/AvatarBookmarks.cpp @@ -144,9 +144,19 @@ void AvatarBookmarks::removeBookmark(const QString& bookmarkName) { emit bookmarkDeleted(bookmarkName); } +bool isWearableEntity(const EntityItemPointer& entity) { + return entity->isVisible() && entity->getParentJointIndex() != INVALID_JOINT_INDEX && + (entity->getParentID() == DependencyManager::get()->getSessionUUID() || entity->getParentID() == DependencyManager::get()->getMyAvatar()->getSelfID()); +} + void AvatarBookmarks::updateAvatarEntities(const QVariantList &avatarEntities) { auto myAvatar = DependencyManager::get()->getMyAvatar(); - myAvatar->removeAvatarEntities(); + auto treeRenderer = DependencyManager::get(); + EntityTreePointer entityTree = treeRenderer ? treeRenderer->getTree() : nullptr; + myAvatar->removeAvatarEntities([&](const QUuid& entityID) { + auto entity = entityTree->findEntityByID(entityID); + return entity && isWearableEntity(entity); + }); addAvatarEntities(avatarEntities); } @@ -163,7 +173,12 @@ void AvatarBookmarks::loadBookmark(const QString& bookmarkName) { QVariantMap bookmark = bookmarkEntry.value().toMap(); if (!bookmark.empty()) { auto myAvatar = DependencyManager::get()->getMyAvatar(); - myAvatar->removeAvatarEntities(); + auto treeRenderer = DependencyManager::get(); + EntityTreePointer entityTree = treeRenderer ? treeRenderer->getTree() : nullptr; + myAvatar->removeAvatarEntities([&](const QUuid& entityID) { + auto entity = entityTree->findEntityByID(entityID); + return entity && isWearableEntity(entity); + }); const QString& avatarUrl = bookmark.value(ENTRY_AVATAR_URL, "").toString(); myAvatar->useFullAvatarURL(avatarUrl); qCDebug(interfaceapp) << "Avatar On " << avatarUrl; @@ -233,6 +248,27 @@ QVariantMap AvatarBookmarks::getAvatarDataToBookmark() { bookmark.insert(ENTRY_AVATAR_URL, avatarUrl); bookmark.insert(ENTRY_AVATAR_SCALE, avatarScale); bookmark.insert(ENTRY_AVATAR_ATTACHMENTS, myAvatar->getAttachmentsVariant()); - bookmark.insert(ENTRY_AVATAR_ENTITIES, myAvatar->getAvatarEntitiesVariant()); + + QScriptEngine scriptEngine; + QVariantList wearableEntities; + auto treeRenderer = DependencyManager::get(); + EntityTreePointer entityTree = treeRenderer ? treeRenderer->getTree() : nullptr; + auto avatarEntities = myAvatar->getAvatarEntityData(); + for (auto entityID : avatarEntities.keys()) { + auto entity = entityTree->findEntityByID(entityID); + if (!entity || !isWearableEntity(entity)) { + continue; + } + QVariantMap avatarEntityData; + EncodeBitstreamParams params; + auto desiredProperties = entity->getEntityProperties(params); + desiredProperties += PROP_LOCAL_POSITION; + desiredProperties += PROP_LOCAL_ROTATION; + EntityItemProperties entityProperties = entity->getProperties(desiredProperties); + QScriptValue scriptProperties = EntityItemPropertiesToScriptValue(&scriptEngine, entityProperties); + avatarEntityData["properties"] = scriptProperties.toVariant(); + wearableEntities.append(QVariant(avatarEntityData)); + } + bookmark.insert(ENTRY_AVATAR_ENTITIES, wearableEntities); return bookmark; } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 6a3ae91dd6..bf7276d5d5 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1608,14 +1608,16 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { emit skeletonModelURLChanged(); } -void MyAvatar::removeAvatarEntities() { +void MyAvatar::removeAvatarEntities(const std::function& condition) { auto treeRenderer = DependencyManager::get(); EntityTreePointer entityTree = treeRenderer ? treeRenderer->getTree() : nullptr; if (entityTree) { entityTree->withWriteLock([&] { AvatarEntityMap avatarEntities = getAvatarEntityData(); for (auto entityID : avatarEntities.keys()) { - entityTree->deleteEntity(entityID, true, true); + if (!condition || condition(entityID)) { + entityTree->deleteEntity(entityID, true, true); + } } }); } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 9b5ddd360d..add00962da 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -33,6 +33,7 @@ #include "MyCharacterController.h" #include "RingBufferHistory.h" #include +#include class AvatarActionHold; class ModelItemID; @@ -926,7 +927,7 @@ public: * @returns {object[]} */ Q_INVOKABLE QVariantList getAvatarEntitiesVariant(); - void removeAvatarEntities(); + void removeAvatarEntities(const std::function& condition = {}); /**jsdoc * @function MyAvatar.isFlying diff --git a/scripts/system/avatarapp.js b/scripts/system/avatarapp.js index 2162b78721..b598649f4f 100644 --- a/scripts/system/avatarapp.js +++ b/scripts/system/avatarapp.js @@ -29,13 +29,25 @@ function executeLater(callback) { Script.setTimeout(callback, 300); } -function getMyAvatarWearables() { - var wearablesArray = MyAvatar.getAvatarEntitiesVariant(); +var INVALID_JOINT_INDEX = -1 +function isWearable(avatarEntity) { + return avatarEntity.properties.visible === true && avatarEntity.properties.parentJointIndex !== INVALID_JOINT_INDEX && + (avatarEntity.properties.parentID === MyAvatar.sessionUUID || avatarEntity.properties.parentID === MyAvatar.SELF_ID); +} - for(var i = 0; i < wearablesArray.length; ++i) { - var wearable = wearablesArray[i]; - var localRotation = wearable.properties.localRotation; - wearable.properties.localRotationAngles = Quat.safeEulerAngles(localRotation) +function getMyAvatarWearables() { + var entitiesArray = MyAvatar.getAvatarEntitiesVariant(); + var wearablesArray = []; + + for (var i = 0; i < entitiesArray.length; ++i) { + var entity = entitiesArray[i]; + if (!isWearable(entity)) { + continue; + } + + var localRotation = entity.properties.localRotation; + entity.properties.localRotationAngles = Quat.safeEulerAngles(localRotation) + wearablesArray.push(entity); } return wearablesArray;