void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason) { auto avatar = std::static_pointer_cast<OtherAvatar>(removedAvatar); AvatarHashMap::handleRemovedAvatar(avatar, removalReason); avatar->tearDownGrabs(); avatar->die(); queuePhysicsChange(avatar); // remove this avatar's entities from the tree now, if we wait (as we did previously) for this Avatar's destructor // it might not fire until after we create a new instance for the same remote avatar, which creates a race // on the creation of entities for that avatar instance and the deletion of entities for this instance avatar->removeAvatarEntitiesFromTree(); if (removalReason != KillAvatarReason::AvatarDisconnected) { if (removalReason == KillAvatarReason::TheirAvatarEnteredYourBubble) { emit AvatarInputs::getInstance()->avatarEnteredIgnoreRadius(avatar->getSessionUUID()); emit DependencyManager::get<UsersScriptingInterface>()->enteredIgnoreRadius(); } workload::Transaction workloadTransaction; workloadTransaction.remove(avatar->getSpaceIndex()); _space->enqueueTransaction(workloadTransaction); const render::ScenePointer& scene = qApp->getMain3DScene(); render::Transaction transaction; avatar->removeFromScene(avatar, scene, transaction); scene->enqueueTransaction(transaction); } else { // remove from node sets, if present DependencyManager::get<NodeList>()->removeFromIgnoreMuteSets(avatar->getSessionUUID()); DependencyManager::get<UsersScriptingInterface>()->avatarDisconnected(avatar->getSessionUUID()); render::Transaction transaction; auto scene = qApp->getMain3DScene(); avatar->fadeOut(transaction, removalReason); workload::SpacePointer space = _space; transaction.transitionFinishedOperator(avatar->getRenderItemID(), [space, avatar]() { if (avatar->getLastFadeRequested() != render::Transition::Type::USER_LEAVE_DOMAIN) { // The avatar is using another transition besides the fade-out transition, which means it is still in use. // Deleting the avatar now could cause state issues, so abort deletion and show message. qCWarning(interfaceapp) << "An ending fade-out transition wants to delete an avatar, but the avatar is still in use. Avatar deletion has aborted. (avatar ID: " << avatar->getSessionUUID() << ")"; } else { const render::ScenePointer& scene = qApp->getMain3DScene(); render::Transaction transaction; avatar->removeFromScene(avatar, scene, transaction); scene->enqueueTransaction(transaction); workload::Transaction workloadTransaction; workloadTransaction.remove(avatar->getSpaceIndex()); space->enqueueTransaction(workloadTransaction); } }); scene->enqueueTransaction(transaction); } }
void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason) { auto avatar = std::static_pointer_cast<OtherAvatar>(removedAvatar); AvatarHashMap::handleRemovedAvatar(avatar, removalReason); avatar->tearDownGrabs(); avatar->die(); queuePhysicsChange(avatar); // remove this avatar's entities from the tree now, if we wait (as we did previously) for this Avatar's destructor // it might not fire until after we create a new instance for the same remote avatar, which creates a race // on the creation of entities for that avatar instance and the deletion of entities for this instance avatar->removeAvatarEntitiesFromTree(); if (removalReason == KillAvatarReason::TheirAvatarEnteredYourBubble) { emit AvatarInputs::getInstance()->avatarEnteredIgnoreRadius(avatar->getSessionUUID()); emit DependencyManager::get<UsersScriptingInterface>()->enteredIgnoreRadius(); workload::Transaction workloadTransaction; workloadTransaction.remove(avatar->getSpaceIndex()); _space->enqueueTransaction(workloadTransaction); const render::ScenePointer& scene = qApp->getMain3DScene(); render::Transaction transaction; avatar->removeFromScene(avatar, scene, transaction); scene->enqueueTransaction(transaction); } else if (removalReason == KillAvatarReason::AvatarDisconnected) { // remove from node sets, if present DependencyManager::get<NodeList>()->removeFromIgnoreMuteSets(avatar->getSessionUUID()); DependencyManager::get<UsersScriptingInterface>()->avatarDisconnected(avatar->getSessionUUID()); render::Transaction transaction; auto scene = qApp->getMain3DScene(); avatar->fadeOut(transaction, removalReason); workload::SpacePointer space = _space; transaction.transitionFinishedOperator(avatar->getRenderItemID(), [space, avatar]() { const render::ScenePointer& scene = qApp->getMain3DScene(); render::Transaction transaction; avatar->removeFromScene(avatar, scene, transaction); scene->enqueueTransaction(transaction); workload::Transaction workloadTransaction; workloadTransaction.remove(avatar->getSpaceIndex()); space->enqueueTransaction(workloadTransaction); }); scene->enqueueTransaction(transaction); } }