mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 03:44:02 +02:00
Merge pull request #15846 from AndrewMeadows/avoid-SafeLanding-event-flood
BUGZ-868: Avoid SafeLanding signal-slot connection resource leak
This commit is contained in:
commit
0b6dfe3f7c
6 changed files with 185 additions and 158 deletions
|
@ -2498,6 +2498,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
pauseUntilLoginDetermined();
|
||||
}
|
||||
|
||||
void Application::setFailedToConnectToEntityServer() {
|
||||
_failedToConnectToEntityServer = true;
|
||||
}
|
||||
|
||||
void Application::updateVerboseLogging() {
|
||||
auto menu = Menu::getInstance();
|
||||
if (!menu) {
|
||||
|
@ -5912,7 +5916,7 @@ void Application::resetPhysicsReadyInformation() {
|
|||
_gpuTextureMemSizeStabilityCount = 0;
|
||||
_gpuTextureMemSizeAtLastCheck = 0;
|
||||
_physicsEnabled = false;
|
||||
_octreeProcessor.startEntitySequence();
|
||||
_octreeProcessor.startSafeLanding();
|
||||
}
|
||||
|
||||
|
||||
|
@ -6162,6 +6166,24 @@ void Application::updateSecondaryCameraViewFrustum() {
|
|||
|
||||
static bool domainLoadingInProgress = false;
|
||||
|
||||
void Application::tryToEnablePhysics() {
|
||||
bool enableInterstitial = DependencyManager::get<NodeList>()->getDomainHandler().getInterstitialModeEnabled();
|
||||
|
||||
if (gpuTextureMemSizeStable() || !enableInterstitial) {
|
||||
_fullSceneCounterAtLastPhysicsCheck = _fullSceneReceivedCounter;
|
||||
_lastQueriedViews.clear(); // Force new view.
|
||||
|
||||
// process octree stats packets are sent in between full sends of a scene (this isn't currently true).
|
||||
// We keep physics disabled until we've received a full scene and everything near the avatar in that
|
||||
// scene is ready to compute its collision shape.
|
||||
if (getMyAvatar()->isReadyForPhysics()) {
|
||||
_physicsEnabled = true;
|
||||
setIsInterstitialMode(false);
|
||||
getMyAvatar()->updateMotionBehaviorFromMenu();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Application::update(float deltaTime) {
|
||||
PROFILE_RANGE_EX(app, __FUNCTION__, 0xffff0000, (uint64_t)_graphicsEngine._renderFrameCount + 1);
|
||||
|
||||
|
@ -6169,7 +6191,6 @@ void Application::update(float deltaTime) {
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!_physicsEnabled) {
|
||||
if (!domainLoadingInProgress) {
|
||||
PROFILE_ASYNC_BEGIN(app, "Scene Loading", "");
|
||||
|
@ -6178,24 +6199,16 @@ void Application::update(float deltaTime) {
|
|||
|
||||
// we haven't yet enabled physics. we wait until we think we have all the collision information
|
||||
// for nearby entities before starting bullet up.
|
||||
quint64 now = usecTimestampNow();
|
||||
if (isServerlessMode() || _octreeProcessor.isLoadSequenceComplete()) {
|
||||
bool enableInterstitial = DependencyManager::get<NodeList>()->getDomainHandler().getInterstitialModeEnabled();
|
||||
|
||||
if (gpuTextureMemSizeStable() || !enableInterstitial) {
|
||||
// we've received a new full-scene octree stats packet, or it's been long enough to try again anyway
|
||||
_lastPhysicsCheckTime = now;
|
||||
_fullSceneCounterAtLastPhysicsCheck = _fullSceneReceivedCounter;
|
||||
_lastQueriedViews.clear(); // Force new view.
|
||||
|
||||
// process octree stats packets are sent in between full sends of a scene (this isn't currently true).
|
||||
// We keep physics disabled until we've received a full scene and everything near the avatar in that
|
||||
// scene is ready to compute its collision shape.
|
||||
if (getMyAvatar()->isReadyForPhysics()) {
|
||||
_physicsEnabled = true;
|
||||
setIsInterstitialMode(false);
|
||||
getMyAvatar()->updateMotionBehaviorFromMenu();
|
||||
}
|
||||
if (isServerlessMode()) {
|
||||
tryToEnablePhysics();
|
||||
} else if (_failedToConnectToEntityServer) {
|
||||
if (_octreeProcessor.safeLandingIsActive()) {
|
||||
_octreeProcessor.stopSafeLanding();
|
||||
}
|
||||
} else {
|
||||
_octreeProcessor.updateSafeLanding();
|
||||
if (_octreeProcessor.safeLandingIsComplete()) {
|
||||
tryToEnablePhysics();
|
||||
}
|
||||
}
|
||||
} else if (domainLoadingInProgress) {
|
||||
|
@ -7144,13 +7157,17 @@ void Application::resettingDomain() {
|
|||
clearDomainOctreeDetails(false);
|
||||
}
|
||||
|
||||
void Application::nodeAdded(SharedNodePointer node) const {
|
||||
void Application::nodeAdded(SharedNodePointer node) {
|
||||
if (node->getType() == NodeType::EntityServer) {
|
||||
if (!_failedToConnectToEntityServer) {
|
||||
if (_failedToConnectToEntityServer && !_entityServerConnectionTimer.isActive()) {
|
||||
_failedToConnectToEntityServer = false;
|
||||
_octreeProcessor.stopSafeLanding();
|
||||
_octreeProcessor.startSafeLanding();
|
||||
} else if (_entityServerConnectionTimer.isActive()) {
|
||||
_entityServerConnectionTimer.stop();
|
||||
_entityServerConnectionTimer.setInterval(ENTITY_SERVER_CONNECTION_TIMEOUT);
|
||||
_entityServerConnectionTimer.start();
|
||||
}
|
||||
_entityServerConnectionTimer.setInterval(ENTITY_SERVER_CONNECTION_TIMEOUT);
|
||||
_entityServerConnectionTimer.start();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7160,7 +7177,6 @@ void Application::nodeActivated(SharedNodePointer node) {
|
|||
|
||||
#if !defined(DISABLE_QML)
|
||||
auto offscreenUi = getOffscreenUI();
|
||||
|
||||
if (offscreenUi) {
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
|
||||
|
|
|
@ -512,7 +512,7 @@ private slots:
|
|||
|
||||
void loadSettings();
|
||||
void saveSettings() const;
|
||||
void setFailedToConnectToEntityServer() { _failedToConnectToEntityServer = true; }
|
||||
void setFailedToConnectToEntityServer();
|
||||
|
||||
bool acceptSnapshot(const QString& urlString);
|
||||
bool askToSetAvatarUrl(const QString& url);
|
||||
|
@ -527,7 +527,7 @@ private slots:
|
|||
|
||||
void domainURLChanged(QUrl domainURL);
|
||||
void updateWindowTitle() const;
|
||||
void nodeAdded(SharedNodePointer node) const;
|
||||
void nodeAdded(SharedNodePointer node);
|
||||
void nodeActivated(SharedNodePointer node);
|
||||
void nodeKilled(SharedNodePointer node);
|
||||
static void packetSent(quint64 length);
|
||||
|
@ -564,6 +564,7 @@ private:
|
|||
void cleanupBeforeQuit();
|
||||
|
||||
void idle();
|
||||
void tryToEnablePhysics();
|
||||
void update(float deltaTime);
|
||||
|
||||
// Various helper functions called during update()
|
||||
|
@ -786,8 +787,6 @@ private:
|
|||
qint64 _gpuTextureMemSizeStabilityCount { 0 };
|
||||
qint64 _gpuTextureMemSizeAtLastCheck { 0 };
|
||||
|
||||
quint64 _lastPhysicsCheckTime { usecTimestampNow() }; // when did we last check to see if physics was ready
|
||||
|
||||
bool _keyboardDeviceHasFocus { true };
|
||||
|
||||
ConnectionMonitor _connectionMonitor;
|
||||
|
|
|
@ -63,7 +63,6 @@ void OctreePacketProcessor::processPacket(QSharedPointer<ReceivedMessage> messag
|
|||
// construct a new packet from the piggybacked one
|
||||
auto buffer = std::unique_ptr<char[]>(new char[piggybackBytes]);
|
||||
memcpy(buffer.get(), message->getRawMessage() + statsMessageLength, piggybackBytes);
|
||||
|
||||
auto newPacket = NLPacket::fromReceivedPacket(std::move(buffer), piggybackBytes, message->getSenderSockAddr());
|
||||
message = QSharedPointer<ReceivedMessage>::create(*newPacket);
|
||||
} else {
|
||||
|
@ -80,7 +79,6 @@ void OctreePacketProcessor::processPacket(QSharedPointer<ReceivedMessage> messag
|
|||
|
||||
const QUuid& senderUUID = sendingNode->getUUID();
|
||||
if (!versionDebugSuppressMap.contains(senderUUID, packetType)) {
|
||||
|
||||
qDebug() << "Was stats packet? " << wasStatsPacket;
|
||||
qDebug() << "OctreePacketProcessor - piggyback packet version mismatch on" << packetType << "- Sender"
|
||||
<< senderUUID << "sent" << (int) message->getVersion() << "but"
|
||||
|
@ -115,7 +113,9 @@ void OctreePacketProcessor::processPacket(QSharedPointer<ReceivedMessage> messag
|
|||
auto renderer = qApp->getEntities();
|
||||
if (renderer) {
|
||||
renderer->processDatagram(*message, sendingNode);
|
||||
_safeLanding->noteReceivedsequenceNumber(renderer->getLastOctreeMessageSequence());
|
||||
if (_safeLanding && _safeLanding->isTracking()) {
|
||||
_safeLanding->addToSequence(renderer->getLastOctreeMessageSequence());
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
@ -124,7 +124,9 @@ void OctreePacketProcessor::processPacket(QSharedPointer<ReceivedMessage> messag
|
|||
// Read sequence #
|
||||
OCTREE_PACKET_SEQUENCE completionNumber;
|
||||
message->readPrimitive(&completionNumber);
|
||||
_safeLanding->setCompletionSequenceNumbers(0, completionNumber);
|
||||
if (_safeLanding) {
|
||||
_safeLanding->finishSequence(0, completionNumber);
|
||||
}
|
||||
} break;
|
||||
|
||||
default: {
|
||||
|
@ -133,6 +135,31 @@ void OctreePacketProcessor::processPacket(QSharedPointer<ReceivedMessage> messag
|
|||
}
|
||||
}
|
||||
|
||||
void OctreePacketProcessor::startEntitySequence() {
|
||||
_safeLanding->startEntitySequence(qApp->getEntities());
|
||||
void OctreePacketProcessor::startSafeLanding() {
|
||||
if (_safeLanding) {
|
||||
_safeLanding->startTracking(qApp->getEntities());
|
||||
}
|
||||
}
|
||||
|
||||
void OctreePacketProcessor::updateSafeLanding() {
|
||||
if (_safeLanding) {
|
||||
_safeLanding->updateTracking();
|
||||
}
|
||||
}
|
||||
|
||||
void OctreePacketProcessor::stopSafeLanding() {
|
||||
if (_safeLanding) {
|
||||
_safeLanding->stopTracking();
|
||||
}
|
||||
}
|
||||
|
||||
bool OctreePacketProcessor::safeLandingIsActive() const {
|
||||
return _safeLanding && _safeLanding->isTracking();
|
||||
}
|
||||
|
||||
bool OctreePacketProcessor::safeLandingIsComplete() const {
|
||||
if (_safeLanding) {
|
||||
return _safeLanding->trackingIsComplete();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -25,8 +25,12 @@ public:
|
|||
OctreePacketProcessor();
|
||||
~OctreePacketProcessor();
|
||||
|
||||
void startEntitySequence();
|
||||
bool isLoadSequenceComplete() const { return _safeLanding->isLoadSequenceComplete(); }
|
||||
void startSafeLanding();
|
||||
void updateSafeLanding();
|
||||
void stopSafeLanding();
|
||||
bool safeLandingIsActive() const;
|
||||
bool safeLandingIsComplete() const;
|
||||
|
||||
float domainLoadingProgress() const { return _safeLanding->loadingProgressPercentage(); }
|
||||
|
||||
signals:
|
||||
|
|
|
@ -33,61 +33,45 @@ bool SafeLanding::SequenceLessThan::operator()(const int& a, const int& b) const
|
|||
return lessThanWraparound<OCTREE_PACKET_SEQUENCE>(a, b);
|
||||
}
|
||||
|
||||
void SafeLanding::startEntitySequence(QSharedPointer<EntityTreeRenderer> entityTreeRenderer) {
|
||||
|
||||
void SafeLanding::startTracking(QSharedPointer<EntityTreeRenderer> entityTreeRenderer) {
|
||||
if (!entityTreeRenderer.isNull()) {
|
||||
auto entityTree = entityTreeRenderer->getTree();
|
||||
if (entityTree) {
|
||||
if (entityTree && !_trackingEntities) {
|
||||
Locker lock(_lock);
|
||||
_entityTreeRenderer = entityTreeRenderer;
|
||||
_trackedEntities.clear();
|
||||
_trackingEntities = true;
|
||||
_maxTrackedEntityCount = 0;
|
||||
_initialStart = INVALID_SEQUENCE;
|
||||
_initialEnd = INVALID_SEQUENCE;
|
||||
_sequenceNumbers.clear();
|
||||
_trackingEntities = true;
|
||||
_startTime = usecTimestampNow();
|
||||
|
||||
connect(std::const_pointer_cast<EntityTree>(entityTree).get(),
|
||||
&EntityTree::addingEntity, this, &SafeLanding::addTrackedEntity, Qt::DirectConnection);
|
||||
connect(std::const_pointer_cast<EntityTree>(entityTree).get(),
|
||||
&EntityTree::deletingEntity, this, &SafeLanding::deleteTrackedEntity);
|
||||
|
||||
_sequenceNumbers.clear();
|
||||
_initialStart = INVALID_SEQUENCE;
|
||||
_initialEnd = INVALID_SEQUENCE;
|
||||
_startTime = usecTimestampNow();
|
||||
EntityTreeRenderer::setEntityLoadingPriorityFunction(&ElevatedPriority);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SafeLanding::stopEntitySequence() {
|
||||
Locker lock(_lock);
|
||||
_trackingEntities = false;
|
||||
_maxTrackedEntityCount = 0;
|
||||
_trackedEntityStabilityCount = 0;
|
||||
_initialStart = INVALID_SEQUENCE;
|
||||
_initialEnd = INVALID_SEQUENCE;
|
||||
_trackedEntities.clear();
|
||||
_sequenceNumbers.clear();
|
||||
}
|
||||
|
||||
void SafeLanding::addTrackedEntity(const EntityItemID& entityID) {
|
||||
if (_trackingEntities) {
|
||||
if (_trackingEntities && _entityTreeRenderer) {
|
||||
Locker lock(_lock);
|
||||
auto entityTree = _entityTreeRenderer->getTree();
|
||||
if (entityTree) {
|
||||
EntityItemPointer entity = entityTree->findEntityByID(entityID);
|
||||
if (entity && !entity->isLocalEntity() && entity->getCreated() < _startTime) {
|
||||
_trackedEntities.emplace(entityID, entity);
|
||||
|
||||
if (_entityTreeRenderer.isNull() || _entityTreeRenderer->getTree() == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
EntityItemPointer entity = _entityTreeRenderer->getTree()->findEntityByID(entityID);
|
||||
|
||||
if (entity && !entity->isLocalEntity() && entity->getCreated() < _startTime) {
|
||||
|
||||
_trackedEntities.emplace(entityID, entity);
|
||||
int trackedEntityCount = (int)_trackedEntities.size();
|
||||
|
||||
if (trackedEntityCount > _maxTrackedEntityCount) {
|
||||
_maxTrackedEntityCount = trackedEntityCount;
|
||||
_trackedEntityStabilityCount = 0;
|
||||
int trackedEntityCount = (int)_trackedEntities.size();
|
||||
if (trackedEntityCount > _maxTrackedEntityCount) {
|
||||
_maxTrackedEntityCount = trackedEntityCount;
|
||||
_trackedEntityStabilityCount = 0;
|
||||
}
|
||||
}
|
||||
//qCDebug(interfaceapp) << "Safe Landing: Tracking entity " << entity->getItemName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -97,32 +81,94 @@ void SafeLanding::deleteTrackedEntity(const EntityItemID& entityID) {
|
|||
_trackedEntities.erase(entityID);
|
||||
}
|
||||
|
||||
void SafeLanding::setCompletionSequenceNumbers(int first, int last) {
|
||||
void SafeLanding::finishSequence(int first, int last) {
|
||||
Locker lock(_lock);
|
||||
if (_initialStart == INVALID_SEQUENCE) {
|
||||
if (_trackingEntities) {
|
||||
_initialStart = first;
|
||||
_initialEnd = last;
|
||||
}
|
||||
}
|
||||
|
||||
void SafeLanding::noteReceivedsequenceNumber(int sequenceNumber) {
|
||||
void SafeLanding::addToSequence(int sequenceNumber) {
|
||||
Locker lock(_lock);
|
||||
if (_trackingEntities) {
|
||||
Locker lock(_lock);
|
||||
_sequenceNumbers.insert(sequenceNumber);
|
||||
}
|
||||
}
|
||||
|
||||
bool SafeLanding::isLoadSequenceComplete() {
|
||||
if ((isEntityLoadingComplete() && isSequenceNumbersComplete()) || qApp->failedToConnectToEntityServer()) {
|
||||
Locker lock(_lock);
|
||||
_initialStart = INVALID_SEQUENCE;
|
||||
_initialEnd = INVALID_SEQUENCE;
|
||||
_entityTreeRenderer.clear();
|
||||
_trackingEntities = false; // Don't track anything else that comes in.
|
||||
EntityTreeRenderer::setEntityLoadingPriorityFunction(StandardPriority);
|
||||
void SafeLanding::updateTracking() {
|
||||
if (!_trackingEntities || !_entityTreeRenderer) {
|
||||
return;
|
||||
}
|
||||
|
||||
return !_trackingEntities;
|
||||
{
|
||||
Locker lock(_lock);
|
||||
bool enableInterstitial = DependencyManager::get<NodeList>()->getDomainHandler().getInterstitialModeEnabled();
|
||||
auto entityMapIter = _trackedEntities.begin();
|
||||
while (entityMapIter != _trackedEntities.end()) {
|
||||
auto entity = entityMapIter->second;
|
||||
bool isVisuallyReady = true;
|
||||
if (enableInterstitial) {
|
||||
auto entityRenderable = _entityTreeRenderer->renderableForEntityId(entityMapIter->first);
|
||||
if (!entityRenderable) {
|
||||
_entityTreeRenderer->addingEntity(entityMapIter->first);
|
||||
}
|
||||
isVisuallyReady = entity->isVisuallyReady() || (!entityRenderable && !entity->isParentPathComplete());
|
||||
}
|
||||
if (isEntityPhysicsReady(entity) && isVisuallyReady) {
|
||||
entityMapIter = _trackedEntities.erase(entityMapIter);
|
||||
} else {
|
||||
if (!isVisuallyReady) {
|
||||
entity->requestRenderUpdate();
|
||||
}
|
||||
entityMapIter++;
|
||||
}
|
||||
}
|
||||
if (enableInterstitial) {
|
||||
_trackedEntityStabilityCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (_trackedEntities.empty()) {
|
||||
// no more tracked entities --> check sequenceNumbers
|
||||
if (_initialStart != INVALID_SEQUENCE) {
|
||||
bool shouldStop = false;
|
||||
{
|
||||
Locker lock(_lock);
|
||||
int sequenceSize = _initialStart <= _initialEnd ? _initialEnd - _initialStart:
|
||||
_initialEnd + SEQUENCE_MODULO - _initialStart;
|
||||
auto startIter = _sequenceNumbers.find(_initialStart);
|
||||
auto endIter = _sequenceNumbers.find(_initialEnd - 1);
|
||||
|
||||
bool missingSequenceNumbers = qApp->isMissingSequenceNumbers();
|
||||
shouldStop = (sequenceSize == 0 ||
|
||||
(startIter != _sequenceNumbers.end() &&
|
||||
endIter != _sequenceNumbers.end() &&
|
||||
((distance(startIter, endIter) == sequenceSize - 1) || !missingSequenceNumbers)));
|
||||
}
|
||||
if (shouldStop) {
|
||||
stopTracking();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SafeLanding::stopTracking() {
|
||||
Locker lock(_lock);
|
||||
_trackingEntities = false;
|
||||
if (_entityTreeRenderer) {
|
||||
auto entityTree = _entityTreeRenderer->getTree();
|
||||
disconnect(std::const_pointer_cast<EntityTree>(entityTree).get(),
|
||||
&EntityTree::addingEntity, this, &SafeLanding::addTrackedEntity);
|
||||
disconnect(std::const_pointer_cast<EntityTree>(entityTree).get(),
|
||||
&EntityTree::deletingEntity, this, &SafeLanding::deleteTrackedEntity);
|
||||
_entityTreeRenderer.reset();
|
||||
}
|
||||
EntityTreeRenderer::setEntityLoadingPriorityFunction(StandardPriority);
|
||||
}
|
||||
|
||||
bool SafeLanding::trackingIsComplete() const {
|
||||
return !_trackingEntities && (_initialStart != INVALID_SEQUENCE);
|
||||
}
|
||||
|
||||
float SafeLanding::loadingProgressPercentage() {
|
||||
|
@ -141,29 +187,6 @@ float SafeLanding::loadingProgressPercentage() {
|
|||
return entityReadyPercentage;
|
||||
}
|
||||
|
||||
bool SafeLanding::isSequenceNumbersComplete() {
|
||||
if (_initialStart != INVALID_SEQUENCE) {
|
||||
Locker lock(_lock);
|
||||
int sequenceSize = _initialStart <= _initialEnd ? _initialEnd - _initialStart:
|
||||
_initialEnd + SEQUENCE_MODULO - _initialStart;
|
||||
auto startIter = _sequenceNumbers.find(_initialStart);
|
||||
auto endIter = _sequenceNumbers.find(_initialEnd - 1);
|
||||
|
||||
bool missingSequenceNumbers = qApp->isMissingSequenceNumbers();
|
||||
if (sequenceSize == 0 ||
|
||||
(startIter != _sequenceNumbers.end()
|
||||
&& endIter != _sequenceNumbers.end()
|
||||
&& ((distance(startIter, endIter) == sequenceSize - 1) || !missingSequenceNumbers))) {
|
||||
bool enableInterstitial = DependencyManager::get<NodeList>()->getDomainHandler().getInterstitialModeEnabled();
|
||||
if (!enableInterstitial) {
|
||||
_trackingEntities = false; // Don't track anything else that comes in.
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SafeLanding::isEntityPhysicsReady(const EntityItemPointer& entity) {
|
||||
if (entity && !entity->getCollisionless()) {
|
||||
const auto& entityType = entity->getType();
|
||||
|
@ -181,52 +204,9 @@ bool SafeLanding::isEntityPhysicsReady(const EntityItemPointer& entity) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SafeLanding::isEntityLoadingComplete() {
|
||||
Locker lock(_lock);
|
||||
|
||||
|
||||
auto entityTree = qApp->getEntities();
|
||||
auto entityMapIter = _trackedEntities.begin();
|
||||
|
||||
bool enableInterstitial = DependencyManager::get<NodeList>()->getDomainHandler().getInterstitialModeEnabled();
|
||||
|
||||
while (entityMapIter != _trackedEntities.end()) {
|
||||
auto entity = entityMapIter->second;
|
||||
|
||||
bool isVisuallyReady = true;
|
||||
|
||||
if (enableInterstitial) {
|
||||
auto entityRenderable = entityTree->renderableForEntityId(entityMapIter->first);
|
||||
if (!entityRenderable) {
|
||||
entityTree->addingEntity(entityMapIter->first);
|
||||
}
|
||||
|
||||
isVisuallyReady = entity->isVisuallyReady() || (!entityRenderable && !entity->isParentPathComplete());
|
||||
}
|
||||
|
||||
if (isEntityPhysicsReady(entity) && isVisuallyReady) {
|
||||
entityMapIter = _trackedEntities.erase(entityMapIter);
|
||||
} else {
|
||||
if (!isVisuallyReady) {
|
||||
entity->requestRenderUpdate();
|
||||
}
|
||||
|
||||
entityMapIter++;
|
||||
}
|
||||
}
|
||||
|
||||
if (enableInterstitial) {
|
||||
_trackedEntityStabilityCount++;
|
||||
}
|
||||
|
||||
|
||||
return _trackedEntities.empty();
|
||||
}
|
||||
|
||||
float SafeLanding::ElevatedPriority(const EntityItem& entityItem) {
|
||||
return entityItem.getCollisionless() ? 0.0f : 10.0f;
|
||||
}
|
||||
|
|
|
@ -25,11 +25,14 @@ class EntityItemID;
|
|||
|
||||
class SafeLanding : public QObject {
|
||||
public:
|
||||
void startEntitySequence(QSharedPointer<EntityTreeRenderer> entityTreeRenderer);
|
||||
void stopEntitySequence();
|
||||
void setCompletionSequenceNumbers(int first, int last); // 'last' exclusive.
|
||||
void noteReceivedsequenceNumber(int sequenceNumber);
|
||||
bool isLoadSequenceComplete();
|
||||
void startTracking(QSharedPointer<EntityTreeRenderer> entityTreeRenderer);
|
||||
void updateTracking();
|
||||
void stopTracking();
|
||||
bool isTracking() const { return _trackingEntities; }
|
||||
bool trackingIsComplete() const;
|
||||
|
||||
void finishSequence(int first, int last); // 'last' exclusive.
|
||||
void addToSequence(int sequenceNumber);
|
||||
float loadingProgressPercentage();
|
||||
|
||||
private slots:
|
||||
|
@ -37,10 +40,8 @@ private slots:
|
|||
void deleteTrackedEntity(const EntityItemID& entityID);
|
||||
|
||||
private:
|
||||
bool isSequenceNumbersComplete();
|
||||
bool isEntityPhysicsReady(const EntityItemPointer& entity);
|
||||
void debugDumpSequenceIDs() const;
|
||||
bool isEntityLoadingComplete();
|
||||
|
||||
std::mutex _lock;
|
||||
using Locker = std::lock_guard<std::mutex>;
|
||||
|
|
Loading…
Reference in a new issue