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 ParabolaPointer::RenderState::update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, float parentScale, bool distanceScaleEnd, bool centerEndY, bool faceAvatar, bool followNormal, float followNormalStrength, float distance, const PickResultPointer& pickResult) { StartEndRenderState::update(origin, end, surfaceNormal, parentScale, distanceScaleEnd, centerEndY, faceAvatar, followNormal, followNormalStrength, distance, pickResult); auto parabolaPickResult = std::static_pointer_cast<ParabolaPickResult>(pickResult); if (parabolaPickResult && render::Item::isValidID(_pathID)) { render::Transaction transaction; auto scene = qApp->getMain3DScene(); PickParabola parabola = PickParabola(parabolaPickResult->pickVariant); glm::vec3 velocity = parabola.velocity; glm::vec3 acceleration = parabola.acceleration; float parabolicDistance = distance > 0.0f ? distance : parabolaPickResult->parabolicDistance; float width = getPathWidth() * parentScale; transaction.updateItem<ParabolaRenderItem>(_pathID, [origin, velocity, acceleration, parabolicDistance, width](ParabolaRenderItem& item) { item.setVisible(true); item.setOrigin(origin); item.setVelocity(velocity); item.setAcceleration(acceleration); item.setParabolicDistance(parabolicDistance); item.setWidth(width); item.updateBounds(); }); 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); } }
void ParabolaPointer::RenderState::cleanup() { StartEndRenderState::cleanup(); if (render::Item::isValidID(_pathID)) { render::Transaction transaction; auto scene = qApp->getMain3DScene(); transaction.removeItem(_pathID); scene->enqueueTransaction(transaction); } }
void ParabolaPointer::RenderState::disable() { StartEndRenderState::disable(); if (render::Item::isValidID(_pathID)) { render::Transaction transaction; auto scene = qApp->getMain3DScene(); transaction.updateItem<ParabolaRenderItem>(_pathID, [](ParabolaRenderItem& item) { item.setVisible(false); }); scene->enqueueTransaction(transaction); } }
ParabolaPointer::RenderState::RenderState(const OverlayID& startID, const OverlayID& endID, const glm::vec3& pathColor, float pathAlpha, float pathWidth, bool isVisibleInSecondaryCamera, bool drawInFront, bool pathEnabled) : StartEndRenderState(startID, endID) { render::Transaction transaction; auto scene = qApp->getMain3DScene(); _pathID = scene->allocateID(); _pathWidth = pathWidth; if (render::Item::isValidID(_pathID)) { auto renderItem = std::make_shared<ParabolaRenderItem>(pathColor, pathAlpha, pathWidth, isVisibleInSecondaryCamera, drawInFront, pathEnabled); transaction.resetItem(_pathID, std::make_shared<ParabolaRenderItem::Payload>(renderItem)); scene->enqueueTransaction(transaction); } }
void ParabolaPointer::RenderState::editParabola(const glm::vec3& color, float alpha, float width, bool isVisibleInSecondaryCamera, bool drawInFront, bool enabled) { if (render::Item::isValidID(_pathID)) { render::Transaction transaction; auto scene = qApp->getMain3DScene(); transaction.updateItem<ParabolaRenderItem>(_pathID, [color, alpha, width, isVisibleInSecondaryCamera, drawInFront, enabled](ParabolaRenderItem& item) { item.setColor(color); item.setAlpha(alpha); item.setWidth(width); item.setIsVisibleInSecondaryCamera(isVisibleInSecondaryCamera); item.setDrawInFront(drawInFront); item.setEnabled(enabled); item.updateKey(); }); scene->enqueueTransaction(transaction); } }