From 092515e19952910a6601be2a2b81f432c0e5b02d Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 22 Nov 2013 15:19:59 -0800 Subject: [PATCH 1/2] Send an explicit kill request to the avatar mixer (which will pass it along to the other clients) when we exit. --- assignment-client/src/avatars/AvatarMixer.cpp | 4 ++- interface/src/Application.cpp | 3 ++ libraries/shared/src/NodeList.cpp | 36 +++++++++++++++++++ libraries/shared/src/NodeList.h | 4 +++ libraries/shared/src/PacketHeaders.h | 1 + 5 files changed, 47 insertions(+), 1 deletion(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 30e1cf2fcf..b13c92e0ed 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -146,6 +146,7 @@ void AvatarMixer::run() { case PACKET_TYPE_INJECT_AUDIO: broadcastAvatarData(nodeList, nodeUUID, &nodeAddress); break; + case PACKET_TYPE_KILL_NODE: case PACKET_TYPE_AVATAR_URLS: case PACKET_TYPE_AVATAR_FACE_VIDEO: nodeUUID = QUuid::fromRfc4122(QByteArray((char*) packetData + numBytesForPacketHeader(packetData), @@ -156,7 +157,8 @@ void AvatarMixer::run() { nodeList->getNodeSocket()->send(node->getActiveSocket(), packetData, receivedBytes); } } - break; + // let node kills fall through to default behavior + default: // hand this off to the NodeList nodeList->processNodeData(&nodeAddress, packetData, receivedBytes); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b9e928e295..eae4c6825a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1394,6 +1394,9 @@ void Application::terminate() { _rearMirrorTools->saveSettings(_settings); _settings->sync(); + // let the avatar mixer know we're out + NodeList::getInstance()->sendKillNode(&NODE_TYPE_AVATAR_MIXER, 1); + if (_enableNetworkThread) { _stopNetworkReceiveThread = true; pthread_join(_networkReceiveThread, NULL); diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index a943d6dde1..daa0d7a4b1 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -162,6 +162,10 @@ void NodeList::processNodeData(sockaddr* senderAddress, unsigned char* packetDat processSTUNResponse(packetData, dataBytes); break; } + case PACKET_TYPE_KILL_NODE: { + processKillNode(packetData, dataBytes); + break; + } } } @@ -449,6 +453,38 @@ void NodeList::processSTUNResponse(unsigned char* packetData, size_t dataBytes) } } +void NodeList::sendKillNode(const char* nodeTypes, int numNodeTypes) { + unsigned char packet[MAX_PACKET_SIZE]; + unsigned char* packetPosition = packet; + + packetPosition += populateTypeAndVersion(packetPosition, PACKET_TYPE_KILL_NODE); + + QByteArray rfcUUID = _ownerUUID.toRfc4122(); + memcpy(packetPosition, rfcUUID.constData(), rfcUUID.size()); + packetPosition += rfcUUID.size(); + + broadcastToNodes(packet, packetPosition - packet, nodeTypes, numNodeTypes); +} + +void NodeList::processKillNode(unsigned char* packetData, size_t dataBytes) { + // skip the header + int numBytesPacketHeader = numBytesForPacketHeader(packetData); + packetData += numBytesPacketHeader; + dataBytes -= numBytesPacketHeader; + + // read the node id + QUuid nodeUUID = QUuid::fromRfc4122(QByteArray((char*)packetData, NUM_BYTES_RFC4122_UUID)); + + packetData += NUM_BYTES_RFC4122_UUID; + dataBytes -= NUM_BYTES_RFC4122_UUID; + + // make sure the node exists + Node* node = nodeWithUUID(nodeUUID); + if (node) { + killNode(node, true); + } +} + void NodeList::sendDomainServerCheckIn() { static bool printedDomainServerIP = false; diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index 47ea2e9e41..1e7b181cb0 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -109,6 +109,8 @@ public: void pingPublicAndLocalSocketsForInactiveNode(Node* node) const; + void sendKillNode(const char* nodeTypes, int numNodeTypes); + Node* nodeWithAddress(sockaddr *senderAddress); Node* nodeWithUUID(const QUuid& nodeUUID); @@ -155,6 +157,8 @@ private: void sendSTUNRequest(); void processSTUNResponse(unsigned char* packetData, size_t dataBytes); + void processKillNode(unsigned char* packetData, size_t dataBytes); + QString _domainHostname; QHostAddress _domainIP; unsigned short _domainPort; diff --git a/libraries/shared/src/PacketHeaders.h b/libraries/shared/src/PacketHeaders.h index a9f320bafd..64a6544cfa 100644 --- a/libraries/shared/src/PacketHeaders.h +++ b/libraries/shared/src/PacketHeaders.h @@ -18,6 +18,7 @@ const PACKET_TYPE PACKET_TYPE_STUN_RESPONSE = 1; const PACKET_TYPE PACKET_TYPE_DOMAIN = 'D'; const PACKET_TYPE PACKET_TYPE_PING = 'P'; const PACKET_TYPE PACKET_TYPE_PING_REPLY = 'R'; +const PACKET_TYPE PACKET_TYPE_KILL_NODE = 'K'; const PACKET_TYPE PACKET_TYPE_HEAD_DATA = 'H'; const PACKET_TYPE PACKET_TYPE_Z_COMMAND = 'Z'; const PACKET_TYPE PACKET_TYPE_INJECT_AUDIO = 'I'; From 083800dc5908e6ebccdc458e32af56d3b7fb8d2c Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 22 Nov 2013 16:23:40 -0800 Subject: [PATCH 2/2] Glow/shrink avatars when killed, send kill message when we move between domains, locations, etc. --- interface/src/Application.cpp | 34 ++++++++++++++++++++++++++++-- interface/src/Application.h | 1 + interface/src/DataServerClient.cpp | 3 +++ interface/src/Menu.cpp | 8 ++++++- interface/src/avatar/MyAvatar.cpp | 4 ---- interface/src/avatar/MyAvatar.h | 2 -- libraries/avatars/src/AvatarData.h | 4 ++++ 7 files changed, 47 insertions(+), 9 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index eae4c6825a..58629df41e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1972,6 +1972,21 @@ void Application::updateAvatars(float deltaTime, glm::vec3 mouseRayOrigin, glm:: } node->unlock(); } + + // simulate avatar fades + for (vector::iterator fade = _avatarFades.begin(); fade != _avatarFades.end(); fade++) { + Avatar* avatar = *fade; + const float SHRINK_RATE = 0.9f; + avatar->setNewScale(avatar->getNewScale() * SHRINK_RATE); + const float MINIMUM_SCALE = 0.001f; + if (avatar->getNewScale() < MINIMUM_SCALE) { + delete avatar; + _avatarFades.erase(fade--); + + } else { + avatar->simulate(deltaTime, NULL); + } + } } void Application::updateMouseRay(float deltaTime, glm::vec3& mouseRayOrigin, glm::vec3& mouseRayDirection) { @@ -3841,6 +3856,12 @@ void Application::renderAvatars(bool forceRenderHead, bool selfAvatarOnly) { node->unlock(); } + + // render avatar fades + Glower glower; + for (vector::iterator fade = _avatarFades.begin(); fade != _avatarFades.end(); fade++) { + (*fade)->render(false, Menu::getInstance()->isOptionChecked(MenuOption::AvatarAsBalls)); + } } // Render my own Avatar @@ -4286,8 +4307,17 @@ void Application::nodeKilled(Node* node) { _voxelServerSceneStats.erase(nodeUUID); } _voxelSceneStatsLock.unlock(); - } else if (node->getLinkedData() == _lookatTargetAvatar) { - _lookatTargetAvatar = NULL; + + } else if (node->getType() == NODE_TYPE_AGENT) { + Avatar* avatar = static_cast(node->getLinkedData()); + if (avatar == _lookatTargetAvatar) { + _lookatTargetAvatar = NULL; + } + + // take over the avatar in order to fade it out + node->setLinkedData(NULL); + + _avatarFades.push_back(avatar); } } diff --git a/interface/src/Application.h b/interface/src/Application.h index 981938f221..4695a1bf80 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -471,6 +471,7 @@ private: QReadWriteLock _voxelSceneStatsLock; std::vector _voxelFades; + std::vector _avatarFades; }; #endif /* defined(__interface__Application__) */ diff --git a/interface/src/DataServerClient.cpp b/interface/src/DataServerClient.cpp index b3d8592027..80be4189b1 100644 --- a/interface/src/DataServerClient.cpp +++ b/interface/src/DataServerClient.cpp @@ -173,6 +173,9 @@ void DataServerClient::processSendFromDataServer(unsigned char* packetData, int if (coordinateItems.size() == 3) { + // send a node kill request, indicating to other clients that they should play the "disappeared" effect + NodeList::getInstance()->sendKillNode(&NODE_TYPE_AVATAR_MIXER, 1); + qDebug() << "Changing domain to" << valueList[i].toLocal8Bit().constData() << "and position to" << valueList[i + 1].toLocal8Bit().constData() << "to go to" << userString << "\n"; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 240c198928..fd942a77c1 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -914,6 +914,9 @@ void Menu::goToDomain() { newHostname = domainDialog.textValue(); } + // send a node kill request, indicating to other clients that they should play the "disappeared" effect + NodeList::getInstance()->sendKillNode(&NODE_TYPE_AVATAR_MIXER, 1); + // give our nodeList the new domain-server hostname NodeList::getInstance()->setDomainHostname(domainDialog.textValue()); } @@ -953,8 +956,11 @@ void Menu::goToLocation() { glm::vec3 newAvatarPos(x, y, z); if (newAvatarPos != avatarPos) { + // send a node kill request, indicating to other clients that they should play the "disappeared" effect + NodeList::getInstance()->sendKillNode(&NODE_TYPE_AVATAR_MIXER, 1); + qDebug("Going To Location: %f, %f, %f...\n", x, y, z); - myAvatar->setPosition(newAvatarPos); + myAvatar->setPosition(newAvatarPos); } } } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 8cdf6100f7..035b5bb80f 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1271,7 +1271,3 @@ void MyAvatar::setOrientation(const glm::quat& orientation) { _bodyYaw = eulerAngles.y; _bodyRoll = eulerAngles.z; } - -void MyAvatar::setNewScale(const float scale) { - _newScale = scale; -} diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index be322d647e..2d90a32108 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -30,12 +30,10 @@ public: void setLeanScale(float scale) { _leanScale = scale; } void setGravity(glm::vec3 gravity); void setOrientation(const glm::quat& orientation); - void setNewScale(const float scale); void setWantCollisionsOn(bool wantCollisionsOn) { _isCollisionsOn = wantCollisionsOn; } void setMoveTarget(const glm::vec3 moveTarget); // getters - float getNewScale() const { return _newScale; } float getSpeed() const { return _speed; } AvatarMode getMode() const { return _mode; } float getLeanScale() const { return _leanScale; } diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 04930c5f6c..b99be1bb09 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -75,6 +75,10 @@ public: float getBodyRoll() const { return _bodyRoll; } void setBodyRoll(float bodyRoll) { _bodyRoll = bodyRoll; } + // Scale + float getNewScale() const { return _newScale; } + void setNewScale(float newScale) { _newScale = newScale; } + // Hand State void setHandState(char s) { _handState = s; } char getHandState() const { return _handState; }