From e7d38446203761abf41fade7de28261f06ac5252 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 11 Jan 2019 15:57:09 -0800 Subject: [PATCH] making pre review requests --- interface/src/Application.cpp | 3 +- .../src/EntityTreeRenderer.cpp | 135 ++++++++++++------ .../src/EntityTreeRenderer.h | 6 +- .../entities/src/EntityScriptingInterface.cpp | 2 +- libraries/entities/src/EntityTree.cpp | 16 ++- libraries/entities/src/EntityTree.h | 2 +- libraries/entities/src/EntityTreeElement.cpp | 4 +- libraries/entities/src/EntityTreeElement.h | 2 +- libraries/octree/src/Octree.h | 2 +- libraries/octree/src/OctreeProcessor.cpp | 34 ++--- libraries/octree/src/OctreeProcessor.h | 2 +- libraries/script-engine/src/ScriptEngine.cpp | 5 + libraries/script-engine/src/ScriptEngine.h | 3 + 13 files changed, 144 insertions(+), 72 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index db29892798..d9e196f55e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6774,8 +6774,7 @@ void Application::clearDomainOctreeDetails(bool clearAll) { }); // reset the model renderer - qDebug() << "-----> clearAll: " << clearAll; - clearAll ? getEntities()->clear() : getEntities()->clearDomainEntities(); + clearAll ? getEntities()->clear() : getEntities()->clearNonLocalEntities(); auto skyStage = DependencyManager::get()->getSkyStage(); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 23b2bda555..8656a000e4 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -197,8 +197,57 @@ void EntityTreeRenderer::resetEntitiesScriptEngine() { }); } -void EntityTreeRenderer::stopEntityScripts() { - leaveAllEntities(); +void EntityTreeRenderer::stopNonLocalEntityScripts() { + leaveNonLocalEntities(); + // unload and stop the engine + if (_entitiesScriptEngine) { + QList entitiesWithEntityScripts = _entitiesScriptEngine->getListOfEntityScriptIDs(); + + foreach (EntityItemID entityID, entitiesWithEntityScripts) { + EntityItemPointer entityItem = getTree()->findEntityByEntityItemID(entityID); + + if (entityItem) { + if (!entityItem->isLocalEntity()) { + _entitiesScriptEngine->unloadEntityScript(entityID, true); + } + } + } + } +} + +void EntityTreeRenderer::clearNonLocalEntities() { + stopNonLocalEntityScripts(); + + std::unordered_map savedEntities; + // remove all entities from the scene + _space->clear(); + 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()) { + renderer->removeFromScene(scene, transaction); + } else { + savedEntities[entry.first] = entry.second; + } + } + scene->enqueueTransaction(transaction); + } else { + qCWarning(entitiesrenderer) << "EntitityTreeRenderer::clear(), Unexpected null scene, possibly during application shutdown"; + } + + _renderablesToUpdate = savedEntities; + _entitiesInScene = savedEntities; + + _layeredZones.clearNonLocalLayeredZones(); + + OctreeProcessor::clearNonLocalEntities(); +} + +void EntityTreeRenderer::clear() { + leaveAllEntities(); // unload and stop the engine if (_entitiesScriptEngine) { // do this here (instead of in deleter) to avoid marshalling unload signals back to this thread @@ -210,44 +259,8 @@ void EntityTreeRenderer::stopEntityScripts() { if (_wantScripts && !_shuttingDown) { resetEntitiesScriptEngine(); } -} - -void EntityTreeRenderer::clearDomainEntities() { - stopEntityScripts(); - - std::unordered_map savedEntities; // remove all entities from the scene - _space->clear(); - 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->isDomainEntity()) { - renderer->removeFromScene(scene, transaction); - } else { - savedEntities[entry.first] = entry.second; - } - } - scene->enqueueTransaction(transaction); - } else { - qCWarning(entitiesrenderer) << "EntitityTreeRenderer::clear(), Unexpected null scene, possibly during application shutdown"; - } - _entitiesInScene.clear(); - _renderablesToUpdate = savedEntities; - _entitiesInScene = savedEntities; - // reset the zone to the default (while we load the next scene) - _layeredZones.clear(); - - OctreeProcessor::clearDomainEntities(); -} - -void EntityTreeRenderer::clear() { - stopEntityScripts(); - - // remove all entities from the scene _space->clear(); auto scene = _viewState->getMain3DScene(); if (scene) { @@ -542,8 +555,7 @@ bool EntityTreeRenderer::findBestZoneAndMaybeContainingEntities(QVector(_tree); // FIXME - if EntityTree had a findEntitiesContainingPoint() this could theoretically be a little faster - entityTree->evalEntitiesInSphere(_avatarPosition, radius, - PickFilter(PickFilter::getBitMask(PickFilter::FlagBit::DOMAIN_ENTITIES) | PickFilter::getBitMask(PickFilter::FlagBit::AVATAR_ENTITIES)), entityIDs); + entityTree->evalEntitiesInSphere(_avatarPosition, radius, PickFilter(), entityIDs); LayeredZones oldLayeredZones(std::move(_layeredZones)); _layeredZones.clear(); @@ -649,6 +661,26 @@ bool EntityTreeRenderer::checkEnterLeaveEntities() { return didUpdate; } +void EntityTreeRenderer::leaveNonLocalEntities() { + if (_tree && !_shuttingDown) { + QVector currentLocalEntitiesInside; + foreach (EntityItemID entityID, _currentEntitiesInside) { + EntityItemPointer entityItem = getTree()->findEntityByEntityItemID(entityID); + if (!entityItem->isLocalEntity()) { + emit leaveEntity(entityID); + if (_entitiesScriptEngine) { + _entitiesScriptEngine->callEntityScriptMethod(entityID, "leaveEntity"); + } + } else { + currentLocalEntitiesInside.push_back(entityID); + } + } + + _currentEntitiesInside = currentLocalEntitiesInside; + forceRecheckEntities(); + } +} + void EntityTreeRenderer::leaveAllEntities() { if (_tree && !_shuttingDown) { @@ -1171,6 +1203,29 @@ EntityTreeRenderer::LayeredZones::LayeredZones(LayeredZones&& other) { } } +void EntityTreeRenderer::LayeredZones::clearNonLocalLayeredZones() { + std::set localLayeredZones; + std::map newMap; + + for (auto iter = begin(); iter != end(); iter++) { + LayeredZone layeredZone = *iter; + + if (layeredZone.zone->isLocalEntity()) { + bool success; + iterator it; + std::tie(it, success) = localLayeredZones.insert(layeredZone); + + if (success) { + newMap.emplace(layeredZone.id, it); + } + } + } + + std::set::operator=(localLayeredZones); + _map = newMap; + _skyboxLayer = empty() ? end() : begin(); +} + void EntityTreeRenderer::LayeredZones::clear() { std::set::clear(); _map.clear(); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index 03d8ca9ff3..d9f594a20b 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -86,7 +86,7 @@ public: virtual void init() override; /// clears the tree - virtual void clearDomainEntities() override; + virtual void clearNonLocalEntities() override; virtual void clear() override; /// reloads the entity scripts, calling unload and preload @@ -162,7 +162,7 @@ private: bool findBestZoneAndMaybeContainingEntities(QVector* entitiesContainingAvatar = nullptr); bool applyLayeredZones(); - void stopEntityScripts(); + void stopNonLocalEntityScripts(); void checkAndCallPreload(const EntityItemID& entityID, bool reload = false, bool unloadFirst = false); @@ -171,6 +171,7 @@ private: QScriptValueList createEntityArgs(const EntityItemID& entityID); bool checkEnterLeaveEntities(); + void leaveNonLocalEntities(); void leaveAllEntities(); void forceRecheckEntities(); @@ -221,6 +222,7 @@ private: LayeredZones& operator=(LayeredZones&&) = delete; void clear(); + void clearNonLocalLayeredZones(); std::pair insert(const LayeredZone& layer); void update(std::shared_ptr zone); bool contains(const LayeredZones& other); diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 697d583de7..286f0dd650 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -986,7 +986,7 @@ void EntityScriptingInterface::deleteEntity(QUuid id) { shouldSendDeleteToServer = false; } else { // only delete local entities, server entities will round trip through the server filters - if (entity->isAvatarEntity() || _entityTree->isServerlessMode()) { + if (!entity->isDomainEntity() || _entityTree->isServerlessMode()) { shouldSendDeleteToServer = false; _entityTree->deleteEntity(entityID); diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index a603d0004b..a2515519eb 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -70,7 +70,7 @@ OctreeElementPointer EntityTree::createNewElement(unsigned char* octalCode) { return std::static_pointer_cast(newElement); } -void EntityTree::eraseDomainEntities() { +void EntityTree::eraseNonLocalEntities() { emit clearingEntities(); if (_simulation) { @@ -84,10 +84,10 @@ void EntityTree::eraseDomainEntities() { foreach(EntityItemPointer entity, localMap) { EntityTreeElementPointer element = entity->getElement(); if (element) { - element->cleanupDomainEntities(); + element->cleanupNonLocalEntities(); } - if (!entity->isDomainEntity()) { + if (entity->isLocalEntity()) { savedEntities[entity->getEntityItemID()] = entity; } } @@ -100,7 +100,15 @@ void EntityTree::eraseDomainEntities() { { QWriteLocker locker(&_needsParentFixupLock); - _needsParentFixup.clear(); + QVector localEntitiesNeedsParentFixup; + + foreach (EntityItemWeakPointer entityItem, _needsParentFixup) { + if (!entityItem.expired() && entityItem.lock()->isLocalEntity()) { + localEntitiesNeedsParentFixup.push_back(entityItem); + } + } + + _needsParentFixup = localEntitiesNeedsParentFixup; } } void EntityTree::eraseAllOctreeElements(bool createNewRoot) { diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index efd994acd2..f9b7b8d67f 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -75,7 +75,7 @@ public: } - virtual void eraseDomainEntities() override; + virtual void eraseNonLocalEntities() override; virtual void eraseAllOctreeElements(bool createNewRoot = true) override; virtual void readBitstreamToTree(const unsigned char* bitstream, diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 8c65dd1c45..d51ffcd10a 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -683,11 +683,11 @@ EntityItemPointer EntityTreeElement::getEntityWithEntityItemID(const EntityItemI return foundEntity; } -void EntityTreeElement::cleanupDomainEntities() { +void EntityTreeElement::cleanupNonLocalEntities() { withWriteLock([&] { EntityItems savedEntities; foreach(EntityItemPointer entity, _entityItems) { - if (entity->isDomainEntity()) { + if (!entity->isLocalEntity()) { entity->preDelete(); entity->_element = NULL; } else { diff --git a/libraries/entities/src/EntityTreeElement.h b/libraries/entities/src/EntityTreeElement.h index 34947fae5c..3f1fda57bd 100644 --- a/libraries/entities/src/EntityTreeElement.h +++ b/libraries/entities/src/EntityTreeElement.h @@ -189,7 +189,7 @@ public: EntityItemPointer getEntityWithEntityItemID(const EntityItemID& id) const; void getEntitiesInside(const AACube& box, QVector& foundEntities); - void cleanupDomainEntities(); + void cleanupNonLocalEntities(); void cleanupEntities(); /// called by EntityTree on cleanup this will free all entities bool removeEntityItem(EntityItemPointer entity, bool deletion = false); diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index 200b3ebd60..aac29201f1 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -149,7 +149,7 @@ public: OctreeElementPointer getRoot() { return _rootElement; } - virtual void eraseDomainEntities() { _isDirty = true; }; + virtual void eraseNonLocalEntities() { _isDirty = true; }; virtual void eraseAllOctreeElements(bool createNewRoot = true); virtual void readBitstreamToTree(const unsigned char* bitstream, uint64_t bufferSizeBytes, ReadBitstreamToTreeParams& args); diff --git a/libraries/octree/src/OctreeProcessor.cpp b/libraries/octree/src/OctreeProcessor.cpp index b3ae0ed113..18c8630391 100644 --- a/libraries/octree/src/OctreeProcessor.cpp +++ b/libraries/octree/src/OctreeProcessor.cpp @@ -51,15 +51,15 @@ void OctreeProcessor::processDatagram(ReceivedMessage& message, SharedNodePointe bool showTimingDetails = false; // Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showTimingDetails, "OctreeProcessor::processDatagram()", showTimingDetails); - + if (message.getType() == getExpectedPacketType()) { PerformanceWarning warn(showTimingDetails, "OctreeProcessor::processDatagram expected PacketType", showTimingDetails); // if we are getting inbound packets, then our tree is also viewing, and we should remember that fact. _tree->setIsViewing(true); - + OCTREE_PACKET_FLAGS flags; message.readPrimitive(&flags); - + OCTREE_PACKET_SEQUENCE sequence; message.readPrimitive(&sequence); @@ -68,7 +68,7 @@ void OctreeProcessor::processDatagram(ReceivedMessage& message, SharedNodePointe bool packetIsColored = oneAtBit(flags, PACKET_IS_COLOR_BIT); bool packetIsCompressed = oneAtBit(flags, PACKET_IS_COMPRESSED_BIT); - + OCTREE_PACKET_SENT_TIME arrivedAt = usecTimestampNow(); qint64 clockSkew = sourceNode ? sourceNode->getClockSkewUsec() : 0; qint64 flightTime = arrivedAt - sentAt + clockSkew; @@ -79,27 +79,27 @@ void OctreeProcessor::processDatagram(ReceivedMessage& message, SharedNodePointe qCDebug(octree) << "OctreeProcessor::processDatagram() ... " "Got Packet Section color:" << packetIsColored << "compressed:" << packetIsCompressed << - "sequence: " << sequence << + "sequence: " << sequence << "flight: " << flightTime << " usec" << "size:" << message.getSize() << "data:" << message.getBytesLeftToRead(); } - + _packetsInLastWindow++; - + int elementsPerPacket = 0; int entitiesPerPacket = 0; - + quint64 totalWaitingForLock = 0; quint64 totalUncompress = 0; quint64 totalReadBitsteam = 0; const QUuid& sourceUUID = sourceNode->getUUID(); - + int subsection = 1; - + bool error = false; - + while (message.getBytesLeftToRead() > 0 && !error) { if (packetIsCompressed) { if (message.getBytesLeftToRead() > (qint64) sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE)) { @@ -111,7 +111,7 @@ void OctreeProcessor::processDatagram(ReceivedMessage& message, SharedNodePointe } else { sectionLength = message.getBytesLeftToRead(); } - + if (sectionLength) { // ask the VoxelTree to read the bitstream into the tree ReadBitstreamToTreeParams args(WANT_EXISTS_BITS, NULL, @@ -149,7 +149,7 @@ void OctreeProcessor::processDatagram(ReceivedMessage& message, SharedNodePointe qCDebug(octree) << "OctreeProcessor::processDatagram() ******* END _tree->readBitstreamToTree()..."; } }); - + // seek forwards in packet message.seek(message.getPosition() + sectionLength); @@ -172,13 +172,13 @@ void OctreeProcessor::processDatagram(ReceivedMessage& message, SharedNodePointe _waitLockPerPacket.updateAverage(totalWaitingForLock); _uncompressPerPacket.updateAverage(totalUncompress); _readBitstreamPerPacket.updateAverage(totalReadBitsteam); - + quint64 now = usecTimestampNow(); if (_lastWindowAt == 0) { _lastWindowAt = now; } quint64 sinceLastWindow = now - _lastWindowAt; - + if (sinceLastWindow > USECS_PER_SECOND) { float packetsPerSecondInWindow = (float)_packetsInLastWindow / (float)(sinceLastWindow / USECS_PER_SECOND); float elementsPerSecondInWindow = (float)_elementsInLastWindow / (float)(sinceLastWindow / USECS_PER_SECOND); @@ -198,10 +198,10 @@ void OctreeProcessor::processDatagram(ReceivedMessage& message, SharedNodePointe } -void OctreeProcessor::clearDomainEntities() { +void OctreeProcessor::clearNonLocalEntities() { if (_tree) { _tree->withWriteLock([&] { - _tree->eraseDomainEntities(); + _tree->eraseNonLocalEntities(); }); } } diff --git a/libraries/octree/src/OctreeProcessor.h b/libraries/octree/src/OctreeProcessor.h index a65531a4d7..bc5618e657 100644 --- a/libraries/octree/src/OctreeProcessor.h +++ b/libraries/octree/src/OctreeProcessor.h @@ -43,7 +43,7 @@ public: virtual void init(); /// clears the tree - virtual void clearDomainEntities(); + virtual void clearNonLocalEntities(); virtual void clear(); float getAverageElementsPerPacket() const { return _elementsPerPacket.getAverage(); } diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 8dad5932be..be17ba04fa 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -2393,6 +2393,11 @@ void ScriptEngine::unloadEntityScript(const EntityItemID& entityID, bool shouldR } } +QList ScriptEngine::getListOfEntityScriptIDs() { + QReadLocker locker{ &_entityScriptsLock }; + return _entityScripts.keys(); +} + void ScriptEngine::unloadAllEntityScripts() { if (QThread::currentThread() != thread()) { #ifdef THREAD_DEBUGGING diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 8fe50aee78..db7d72fff8 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -145,6 +145,9 @@ public: QString getFilename() const; + + QList getListOfEntityScriptIDs(); + /**jsdoc * Stop the current script. * @function Script.stop