From 703a4a570028adec099ab99c6d0d78b0942f8379 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 19 Apr 2019 14:53:23 -0700 Subject: [PATCH] call leaveEntity when script stops --- .../src/EntityTreeRenderer.cpp | 59 ++++++++++--------- .../src/EntityTreeRenderer.h | 5 +- 2 files changed, 35 insertions(+), 29 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 6cfff7bc41..7d130125b3 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -205,8 +205,11 @@ void EntityTreeRenderer::stopDomainAndNonOwnedEntities() { foreach (const EntityItemID& entityID, entitiesWithEntityScripts) { EntityItemPointer entityItem = getTree()->findEntityByEntityItemID(entityID); - if (entityItem) { + if (entityItem && !entityItem->getScript().isEmpty()) { if (!(entityItem->isLocalEntity() || (entityItem->isAvatarEntity() && entityItem->getOwningAvatarID() == getTree()->getMyAvatarSessionUUID()))) { + if (entityItem->contains(_avatarPosition)) { + _entitiesScriptEngine->callEntityScriptMethod(entityID, "leaveEntity"); + } _entitiesScriptEngine->unloadEntityScript(entityID, true); } } @@ -534,7 +537,7 @@ void EntityTreeRenderer::handleSpaceUpdate(std::pair proxyUp _spaceUpdates.emplace_back(proxyUpdate.first, proxyUpdate.second); } -bool EntityTreeRenderer::findBestZoneAndMaybeContainingEntities(QVector* entitiesContainingAvatar) { +bool EntityTreeRenderer::findBestZoneAndMaybeContainingEntities(QSet& entitiesContainingAvatar) { bool didUpdate = false; float radius = 0.01f; // for now, assume 0.01 meter radius, because we actually check the point inside later QVector entityIDs; @@ -580,9 +583,7 @@ bool EntityTreeRenderer::findBestZoneAndMaybeContainingEntities(QVectorgetEntityItemID(); - } + entitiesContainingAvatar << entity->getEntityItemID(); } } } @@ -616,36 +617,36 @@ bool EntityTreeRenderer::checkEnterLeaveEntities() { auto movedEnough = glm::distance(avatarPosition, _avatarPosition) > ZONE_CHECK_DISTANCE; auto enoughTimeElapsed = (now - _lastZoneCheck) > ZONE_CHECK_INTERVAL; - if (movedEnough || enoughTimeElapsed) { + if (_forceRecheckEntities || movedEnough || enoughTimeElapsed) { _avatarPosition = avatarPosition; _lastZoneCheck = now; - QVector entitiesContainingAvatar; - didUpdate = findBestZoneAndMaybeContainingEntities(&entitiesContainingAvatar); - + _forceRecheckEntities = false; + + QSet entitiesContainingAvatar; + didUpdate = findBestZoneAndMaybeContainingEntities(entitiesContainingAvatar); + // Note: at this point we don't need to worry about the tree being locked, because we only deal with // EntityItemIDs from here. The callEntityScriptMethod() method is robust against attempting to call scripts // for entity IDs that no longer exist. - // for all of our previous containing entities, if they are no longer containing then send them a leave event - foreach(const EntityItemID& entityID, _currentEntitiesInside) { - if (!entitiesContainingAvatar.contains(entityID)) { - emit leaveEntity(entityID); - if (_entitiesScriptEngine) { + if (_entitiesScriptEngine) { + // for all of our previous containing entities, if they are no longer containing then send them a leave event + foreach(const EntityItemID& entityID, _currentEntitiesInside) { + if (!entitiesContainingAvatar.contains(entityID)) { + emit leaveEntity(entityID); _entitiesScriptEngine->callEntityScriptMethod(entityID, "leaveEntity"); } } - } - // for all of our new containing entities, if they weren't previously containing then send them an enter event - foreach(const EntityItemID& entityID, entitiesContainingAvatar) { - if (!_currentEntitiesInside.contains(entityID)) { - emit enterEntity(entityID); - if (_entitiesScriptEngine) { + // for all of our new containing entities, if they weren't previously containing then send them an enter event + foreach(const EntityItemID& entityID, entitiesContainingAvatar) { + if (!_currentEntitiesInside.contains(entityID)) { + emit enterEntity(entityID); _entitiesScriptEngine->callEntityScriptMethod(entityID, "enterEntity"); } } + _currentEntitiesInside = entitiesContainingAvatar; } - _currentEntitiesInside = entitiesContainingAvatar; } } return didUpdate; @@ -653,7 +654,7 @@ bool EntityTreeRenderer::checkEnterLeaveEntities() { void EntityTreeRenderer::leaveDomainAndNonOwnedEntities() { if (_tree && !_shuttingDown) { - QVector currentEntitiesInsideToSave; + QSet currentEntitiesInsideToSave; foreach (const EntityItemID& entityID, _currentEntitiesInside) { EntityItemPointer entityItem = getTree()->findEntityByEntityItemID(entityID); if (!(entityItem->isLocalEntity() || (entityItem->isAvatarEntity() && entityItem->getOwningAvatarID() == getTree()->getMyAvatarSessionUUID()))) { @@ -662,7 +663,7 @@ void EntityTreeRenderer::leaveDomainAndNonOwnedEntities() { _entitiesScriptEngine->callEntityScriptMethod(entityID, "leaveEntity"); } } else { - currentEntitiesInsideToSave.push_back(entityID); + currentEntitiesInsideToSave.insert(entityID); } } @@ -687,9 +688,7 @@ void EntityTreeRenderer::leaveAllEntities() { } void EntityTreeRenderer::forceRecheckEntities() { - // make sure our "last avatar position" is something other than our current position, - // so that on our next chance, we'll check for enter/leave entity events. - _avatarPosition = _viewState->getAvatarPosition() + glm::vec3((float)TREE_SCALE); + _forceRecheckEntities = true; } bool EntityTreeRenderer::applyLayeredZones() { @@ -992,7 +991,10 @@ void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) { return; } - if (_tree && !_shuttingDown && _entitiesScriptEngine) { + if (_tree && !_shuttingDown && _entitiesScriptEngine && !itr->second->getEntity()->getScript().isEmpty()) { + if (itr->second->getEntity()->contains(_avatarPosition)) { + _entitiesScriptEngine->callEntityScriptMethod(entityID, "leaveEntity"); + } _entitiesScriptEngine->unloadEntityScript(entityID, true); } @@ -1038,6 +1040,9 @@ void EntityTreeRenderer::checkAndCallPreload(const EntityItemID& entityID, bool QString scriptUrl = entity->getScript(); if ((shouldLoad && unloadFirst) || scriptUrl.isEmpty()) { if (_entitiesScriptEngine) { + if (entity->contains(_avatarPosition)) { + _entitiesScriptEngine->callEntityScriptMethod(entityID, "leaveEntity"); + } _entitiesScriptEngine->unloadEntityScript(entityID); } entity->scriptHasUnloaded(); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index cee91ad1c7..05105a2c7f 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -169,7 +169,7 @@ private: void resetEntitiesScriptEngine(); - bool findBestZoneAndMaybeContainingEntities(QVector* entitiesContainingAvatar = nullptr); + bool findBestZoneAndMaybeContainingEntities(QSet& entitiesContainingAvatar); bool applyLayeredZones(); void stopDomainAndNonOwnedEntities(); @@ -186,7 +186,8 @@ private: void forceRecheckEntities(); glm::vec3 _avatarPosition { 0.0f }; - QVector _currentEntitiesInside; + bool _forceRecheckEntities { true }; + QSet _currentEntitiesInside; bool _wantScripts; ScriptEnginePointer _entitiesScriptEngine;