diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index aa1847f64b..fea0652964 100755 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -531,7 +531,7 @@ void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar // 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(); - + avatar->setIsFading(false); if (removalReason == KillAvatarReason::TheirAvatarEnteredYourBubble) { emit DependencyManager::get()->enteredIgnoreRadius(); } else if (removalReason == KillAvatarReason::AvatarDisconnected) { @@ -540,12 +540,11 @@ void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar DependencyManager::get()->avatarDisconnected(avatar->getSessionUUID()); render::Transaction transaction; auto scene = qApp->getMain3DScene(); - avatar->fadeOut(scene, removalReason); + avatar->fadeOut(transaction, removalReason); transaction.transitionFinishedOperator(avatar->getRenderItemID(), [avatar]() { avatar->setIsFading(false); }); - scene->enqueueTransaction(transaction); } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 96a545fa97..dccf37c5b8 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -659,9 +659,8 @@ void Avatar::fadeIn(render::ScenePointer scene) { scene->enqueueTransaction(transaction); } -void Avatar::fadeOut(render::ScenePointer scene, KillAvatarReason reason) { +void Avatar::fadeOut(render::Transaction& transaction, KillAvatarReason reason) { render::Transition::Type transitionType = render::Transition::USER_LEAVE_DOMAIN; - render::Transaction transaction; if (reason == KillAvatarReason::YourAvatarEnteredTheirBubble) { transitionType = render::Transition::BUBBLE_ISECT_TRESPASSER; @@ -669,7 +668,6 @@ void Avatar::fadeOut(render::ScenePointer scene, KillAvatarReason reason) { transitionType = render::Transition::BUBBLE_ISECT_OWNER; } fade(transaction, transitionType); - scene->enqueueTransaction(transaction); } void Avatar::fade(render::Transaction& transaction, render::Transition::Type type) { diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index da04c4adf7..b4cad4f967 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -461,7 +461,7 @@ public: bool isMoving() const { return _moving; } void fadeIn(render::ScenePointer scene); - void fadeOut(render::ScenePointer scene, KillAvatarReason reason); + void fadeOut(render::Transaction& transaction, KillAvatarReason reason); bool isFading() const { return _isFading; } void setIsFading(bool isFading) { _isFading = isFading; } diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 3eed625916..2701467a2d 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -214,6 +214,30 @@ void EntityTreeRenderer::stopDomainAndNonOwnedEntities() { } } +void EntityTreeRenderer::removeFadedRenderables() { + if (_entityRenderablesToFadeOut.empty()) { + return; + } + + std::unique_lock lock(_entitiesToFadeLock); + auto entityIter = _entityRenderablesToFadeOut.begin(); + auto scene = _viewState->getMain3DScene(); + render::Transaction transaction; + + while (entityIter != _entityRenderablesToFadeOut.end()) { + auto entityRenderable = *entityIter; + + if (!entityRenderable->getIsFading()) { + entityRenderable->removeFromScene(scene, transaction); + entityIter = _entityRenderablesToFadeOut.erase(entityIter); + } else { + ++entityIter; + } + } + + scene->enqueueTransaction(transaction); +} + void EntityTreeRenderer::clearDomainAndNonOwnedEntities() { stopDomainAndNonOwnedEntities(); @@ -221,17 +245,15 @@ void EntityTreeRenderer::clearDomainAndNonOwnedEntities() { // remove all entities from the scene auto scene = _viewState->getMain3DScene(); if (scene) { - render::Transaction transaction; for (const auto& entry : _entitiesInScene) { const auto& renderer = entry.second; const EntityItemPointer& entityItem = renderer->getEntity(); if (!(entityItem->isLocalEntity() || (entityItem->isAvatarEntity() && entityItem->getOwningAvatarID() == getTree()->getMyAvatarSessionUUID()))) { - renderer->removeFromScene(scene, transaction); + fadeOutRenderable(renderer); } else { savedEntities[entry.first] = entry.second; } } - scene->enqueueTransaction(transaction); } _renderablesToUpdate = savedEntities; @@ -258,12 +280,10 @@ void EntityTreeRenderer::clear() { // remove all entities from the scene auto scene = _viewState->getMain3DScene(); if (scene) { - render::Transaction transaction; for (const auto& entry : _entitiesInScene) { const auto& renderer = entry.second; - renderer->removeFromScene(scene, transaction); + fadeOutRenderable(renderer); } - scene->enqueueTransaction(transaction); } else { qCWarning(entitiesrenderer) << "EntitityTreeRenderer::clear(), Unexpected null scene, possibly during application shutdown"; } @@ -531,6 +551,7 @@ void EntityTreeRenderer::update(bool simulate) { } } + removeFadedRenderables(); } void EntityTreeRenderer::handleSpaceUpdate(std::pair proxyUpdate) { @@ -1016,10 +1037,7 @@ void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) { forceRecheckEntities(); // reset our state to force checking our inside/outsideness of entities - // here's where we remove the entity payload from the scene - render::Transaction transaction; - renderable->removeFromScene(scene, transaction); - scene->enqueueTransaction(transaction); + fadeOutRenderable(renderable); } void EntityTreeRenderer::addingEntity(const EntityItemID& entityID) { @@ -1057,24 +1075,26 @@ void EntityTreeRenderer::checkAndCallPreload(const EntityItemID& entityID, bool } } -void EntityTreeRenderable::fadeOutRenderable(const EntityRendererPointer& renderable) { +void EntityTreeRenderer::fadeOutRenderable(const EntityRendererPointer& renderable) { render::Transaction transaction; - auto scene = qApp->getMain3DScene(); + auto scene = _viewState->getMain3DScene(); + renderable->setIsFading(true); transaction.transitionFinishedOperator(renderable->getRenderItemID(), [renderable]() { renderable->setIsFading(false); }); scene->enqueueTransaction(transaction); + _entityRenderablesToFadeOut.push_back(renderable); } void EntityTreeRenderer::playEntityCollisionSound(const EntityItemPointer& entity, const Collision& collision) { assert((bool)entity); auto renderable = renderableForEntity(entity); - if (!renderable) { - return; + if (!renderable) { + return; } - + SharedSoundPointer collisionSound = renderable->getCollisionSound(); if (!collisionSound) { return; diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index 4d6c0e3ba2..32504abd56 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -93,7 +93,7 @@ public: /// reloads the entity scripts, calling unload and preload void reloadEntityScripts(); - void fadeOutRenderable(const EntityRenderablePointer& renderable); + void fadeOutRenderable(const EntityRendererPointer& renderable); void removeFadedRenderables(); // event handles which may generate entity related events @@ -258,7 +258,9 @@ private: std::unordered_map _renderablesToUpdate; std::unordered_map _entitiesInScene; std::unordered_map _entitiesToAdd; - std::vector _entityRendersToFadeOut; + + std::mutex _entitiesToFadeLock; + std::vector _entityRenderablesToFadeOut; // For Scene.shouldRenderEntities QList _entityIDsLastInScene; diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index a6826da91b..e4e135cd7f 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -148,7 +148,7 @@ EntityRenderer::EntityRenderer(const EntityItemPointer& entity) : _created(entit }); } -EntityRenderer::~EntityRenderer() { } +EntityRenderer::~EntityRenderer() {} // // Smart payload proxy members, implementing the payload interface @@ -418,9 +418,7 @@ void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transa if (fading || _prevIsTransparent != transparent) { emit requestRenderUpdate(); } - if (fading) { - _isFading = Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f; - } + _prevIsTransparent = transparent; updateModelTransformAndBound(); @@ -493,4 +491,4 @@ glm::vec4 EntityRenderer::calculatePulseColor(const glm::vec4& color, const Puls } return result; -} \ No newline at end of file +} diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index ad6523ce11..c93054d5fe 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -461,8 +461,8 @@ void Scene::resetTransitionFinishedOperator(const Transaction::TransitionFinishe TransitionStage::Index transitionId = item.getTransitionId(); if (!TransitionStage::isIndexInvalid(transitionId)) { _transitionFinishedOperatorMap[transitionId].emplace_back(func); - } else { - fucn(); + } else if (func) { + func(); } } } @@ -559,7 +559,7 @@ void Scene::resetItemTransition(ItemID itemId) { auto transitionStage = getStage(TransitionStage::getName()); auto finishedOperators = _transitionFinishedOperatorMap[transitionId]; - + qDebug() << "removing transition: " << transitionId; for (auto finishedOperator : finishedOperators) { if (finishedOperator) { finishedOperator(); diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index e2195cf8c1..08fbf33bcd 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -34,6 +34,7 @@ class Scene; // of updating the scene before it s rendered. // + class Transaction { friend class Scene; public: @@ -230,7 +231,7 @@ protected: mutable std::mutex _selectionsMutex; // mutable so it can be used in the thread safe getSelection const method SelectionMap _selections; - std::unordered_map> _transitionFinishedOperatorMap; + std::unordered_map> _transitionFinishedOperatorMap; void resetSelections(const Transaction::SelectionResets& transactions); // More actions coming to selections soon: