예제 #1
0
void AvatarManager::removeDeadAvatarEntities(const SetOfEntities& deadEntities) {
    auto treeRenderer = DependencyManager::get<EntityTreeRenderer>();
    EntityTreePointer entityTree = treeRenderer ? treeRenderer->getTree() : nullptr;
    for (auto entity : deadEntities) {
        QUuid entityOwnerID = entity->getOwningAvatarID();
        AvatarSharedPointer avatar = getAvatarBySessionID(entityOwnerID);
        const bool REQUIRES_REMOVAL_FROM_TREE = false;
        if (avatar) {
            avatar->clearAvatarEntity(entity->getID(), REQUIRES_REMOVAL_FROM_TREE);
        }
        if (entityTree && entity->isMyAvatarEntity()) {
            entityTree->withWriteLock([&] {
                // We only need to delete the direct children (rather than the descendants) because
                // when the child is deleted, it will take care of its own children.  If the child
                // is also an avatar-entity, we'll end up back here.  If it's not, the entity-server
                // will take care of it in the usual way.
                entity->forEachChild([&](SpatiallyNestablePointer child) {
                    EntityItemPointer childEntity = std::dynamic_pointer_cast<EntityItem>(child);
                    if (childEntity) {
                        entityTree->deleteEntity(childEntity->getID(), true, true);
                        if (avatar) {
                            avatar->clearAvatarEntity(childEntity->getID(), REQUIRES_REMOVAL_FROM_TREE);
                        }
                    }
                });
            });
        }
    }
}
예제 #2
0
void AvatarManager::updateOtherAvatars(float deltaTime) {
    if (_avatarHash.size() < 2 && _avatarFades.isEmpty()) {
        return;
    }
    bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
    PerformanceWarning warn(showWarnings, "Application::updateAvatars()");

    PerformanceTimer perfTimer("otherAvatars");
    
    // simulate avatars
    AvatarHash::iterator avatarIterator = _avatarHash.begin();
    while (avatarIterator != _avatarHash.end()) {
        AvatarSharedPointer sharedAvatar = avatarIterator.value();
        Avatar* avatar = reinterpret_cast<Avatar*>(sharedAvatar.data());
        
        if (sharedAvatar == _myAvatar || !avatar->isInitialized()) {
            // DO NOT update _myAvatar!  Its update has already been done earlier in the main loop.
            // DO NOT update uninitialized Avatars
            ++avatarIterator;
            continue;
        }
        if (!shouldKillAvatar(sharedAvatar)) {
            // this avatar's mixer is still around, go ahead and simulate it
            avatar->simulate(deltaTime);
            ++avatarIterator;
        } else {
            // the mixer that owned this avatar is gone, give it to the vector of fades and kill it
            avatarIterator = erase(avatarIterator);
        }
    }
    
    // simulate avatar fades
    simulateAvatarFades(deltaTime);
}
예제 #3
0
void AvatarManager::removeDeadAvatarEntities(const SetOfEntities& deadEntities) {
    for (auto entity : deadEntities) {
        QUuid sessionID = entity->getOwningAvatarID();
        AvatarSharedPointer avatar = getAvatarBySessionID(sessionID);
        if (avatar) {
            const bool REQUIRES_REMOVAL_FROM_TREE = false;
            avatar->clearAvatarEntity(entity->getID(), REQUIRES_REMOVAL_FROM_TREE);
        }
    }
}
예제 #4
0
void AvatarHashMap::processAvatarBillboardPacket(const QByteArray& packet, const QWeakPointer<Node>& mixerWeakPointer) {
    int headerSize = numBytesForPacketHeader(packet);
    QUuid sessionUUID = QUuid::fromRfc4122(QByteArray::fromRawData(packet.constData() + headerSize, NUM_BYTES_RFC4122_UUID));
    
    AvatarSharedPointer matchingAvatar = matchingOrNewAvatar(sessionUUID, mixerWeakPointer);
    if (matchingAvatar) {
        QByteArray billboard = packet.mid(headerSize + NUM_BYTES_RFC4122_UUID);
        if (matchingAvatar->getBillboard() != billboard) {
            matchingAvatar->setBillboard(billboard);
        }
    }
}
예제 #5
0
AvatarSharedPointer AvatarHashMap::matchingOrNewAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) {
    AvatarSharedPointer matchingAvatar = _avatarHash.value(sessionUUID);
    
    if (!matchingAvatar) {
        // insert the new avatar into our hash
        matchingAvatar = newSharedAvatar();
    
        qDebug() << "Adding avatar with sessionUUID " << sessionUUID << "to AvatarHashMap.";
        _avatarHash.insert(sessionUUID, matchingAvatar);
        
        matchingAvatar->setOwningAvatarMixer(mixerWeakPointer);
    }
    
    return matchingAvatar;
}
예제 #6
0
void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar) {
    AvatarHashMap::handleRemovedAvatar(removedAvatar);

    removedAvatar->die();
    removeAvatarMotionState(removedAvatar);
    _avatarFades.push_back(removedAvatar);
}
예제 #7
0
void AvatarHashMap::processAvatarDataPacket(const QByteArray &datagram, const QWeakPointer<Node> &mixerWeakPointer) {
    int bytesRead = numBytesForPacketHeader(datagram);
    
    // enumerate over all of the avatars in this packet
    // only add them if mixerWeakPointer points to something (meaning that mixer is still around)
    while (bytesRead < datagram.size() && mixerWeakPointer.data()) {
        QUuid sessionUUID = QUuid::fromRfc4122(datagram.mid(bytesRead, NUM_BYTES_RFC4122_UUID));
        bytesRead += NUM_BYTES_RFC4122_UUID;
        
        if (sessionUUID != _lastOwnerSessionUUID) {
            AvatarSharedPointer matchingAvatarData = matchingOrNewAvatar(sessionUUID, mixerWeakPointer);
            
            // have the matching (or new) avatar parse the data from the packet
            bytesRead += matchingAvatarData->parseDataAtOffset(datagram, bytesRead);
        } else {
            // create a dummy AvatarData class to throw this data on the ground
            AvatarData dummyData;
            bytesRead += dummyData.parseDataAtOffset(datagram, bytesRead);
        }
    }
}
예제 #8
0
void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar) {
    AvatarHashMap::handleRemovedAvatar(removedAvatar);

    // removedAvatar is a shared pointer to an AvatarData but we need to get to the derived Avatar
    // class in this context so we can call methods that don't exist at the base class.
    Avatar* avatar = static_cast<Avatar*>(removedAvatar.get());
    avatar->die();

    AvatarMotionState* motionState = avatar->getMotionState();
    if (motionState) {
        _motionStatesThatMightUpdate.remove(motionState);
        _motionStatesToAddToPhysics.remove(motionState);
        _motionStatesToRemoveFromPhysics.push_back(motionState);
    }

    _avatarFades.push_back(removedAvatar);
}
예제 #9
0
void AvatarHashMap::processAvatarIdentityPacket(const QByteArray &packet, const QWeakPointer<Node>& mixerWeakPointer) {
    // setup a data stream to parse the packet
    QDataStream identityStream(packet);
    identityStream.skipRawData(numBytesForPacketHeader(packet));
    
    QUuid sessionUUID;
    
    while (!identityStream.atEnd()) {
        
        QUrl faceMeshURL, skeletonURL;
        QVector<AttachmentData> attachmentData;
        QString displayName;
        identityStream >> sessionUUID >> faceMeshURL >> skeletonURL >> attachmentData >> displayName;
        
        // mesh URL for a UUID, find avatar in our list
        AvatarSharedPointer matchingAvatar = matchingOrNewAvatar(sessionUUID, mixerWeakPointer);
        if (matchingAvatar) {
            
            if (matchingAvatar->getFaceModelURL() != faceMeshURL) {
                matchingAvatar->setFaceModelURL(faceMeshURL);
            }
            
            if (matchingAvatar->getSkeletonModelURL() != skeletonURL) {
                matchingAvatar->setSkeletonModelURL(skeletonURL);
            }
            
            if (matchingAvatar->getAttachmentData() != attachmentData) {
                matchingAvatar->setAttachmentData(attachmentData);
            }
            
            if (matchingAvatar->getDisplayName() != displayName) {
                matchingAvatar->setDisplayName(displayName);
            }
        }
    }
}
예제 #10
0
bool AvatarHashMap::shouldKillAvatar(const AvatarSharedPointer& sharedAvatar) {
    return (sharedAvatar->getOwningAvatarMixer() == NULL
            || sharedAvatar->getLastUpdateTimer().elapsed() > AVATAR_SILENCE_THRESHOLD_MSECS);
}
예제 #11
0
void AvatarHashMap::insert(const QUuid& sessionUUID, AvatarSharedPointer avatar) {
    _avatarHash.insert(sessionUUID, avatar);
    avatar->setSessionUUID(sessionUUID);
}