From c76ae56d64c6f8b25f5d1a55743d7a818807703c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 5 May 2015 11:00:27 -0700 Subject: [PATCH 01/39] allow optional sequence numbers in packets --- libraries/networking/src/LimitedNodeList.cpp | 33 ++++-- libraries/networking/src/LimitedNodeList.h | 12 ++- libraries/networking/src/PacketHeaders.cpp | 100 +++++++++++++------ libraries/networking/src/PacketHeaders.h | 45 ++++++--- 4 files changed, 135 insertions(+), 55 deletions(-) diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index e5badc32eb..b125394103 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -231,20 +231,13 @@ qint64 LimitedNodeList::readDatagram(QByteArray& incomingPacket, QHostAddress* a } qint64 LimitedNodeList::writeDatagram(const QByteArray& datagram, const HifiSockAddr& destinationSockAddr, - const QUuid& connectionSecret) { - QByteArray datagramCopy = datagram; - - if (!connectionSecret.isNull()) { - // setup the MD5 hash for source verification in the header - replaceHashInPacketGivenConnectionUUID(datagramCopy, connectionSecret); - } - + const QUuid& connectionSecret) { // XXX can BandwidthRecorder be used for this? // stat collection for packets ++_numCollectedPackets; _numCollectedBytes += datagram.size(); - qint64 bytesWritten = _nodeSocket.writeDatagram(datagramCopy, + qint64 bytesWritten = _nodeSocket.writeDatagram(datagram, destinationSockAddr.getAddress(), destinationSockAddr.getPort()); if (bytesWritten < 0) { @@ -270,6 +263,19 @@ qint64 LimitedNodeList::writeDatagram(const QByteArray& datagram, } } + QByteArray datagramCopy = datagram; + PacketType packetType = packetTypeForPacket(datagramCopy); + + // perform replacement of hash and optionally also sequence number in the header + if (SEQUENCE_NUMBERED_PACKETS.contains(packetType)) { + PacketSequenceNumber sequenceNumber = getNextSequenceNumberForPacket(destinationNode->getUUID(), packetType); + replaceHashAndSequenceNumberInPacketGivenType(datagramCopy, packetType, + destinationNode->getConnectionSecret(), + sequenceNumber); + } else { + replaceHashInPacketGivenType(datagramCopy, packetType, destinationNode->getConnectionSecret()); + } + emit dataSent(destinationNode->getType(), datagram.size()); auto bytesWritten = writeDatagram(datagram, *destinationSockAddr, destinationNode->getConnectionSecret()); // Keep track of per-destination-node bandwidth @@ -318,6 +324,15 @@ qint64 LimitedNodeList::writeUnverifiedDatagram(const char* data, qint64 size, c return writeUnverifiedDatagram(QByteArray(data, size), destinationNode, overridenSockAddr); } +PacketSequenceNumber LimitedNodeList::getNextSequenceNumberForPacket(const QUuid& nodeUUID, PacketType packetType) { + // Thanks to std::map and std::unordered_map this line either default constructs the + // PacketTypeSequenceMap and the PacketSequenceNumber or returns the existing value. + // We use the postfix increment so that the stored value is incremented and the next + // return gives the correct value. + + return _packetSequenceNumbers[nodeUUID][packetType]++; +} + void LimitedNodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteArray& packet) { // the node decided not to do anything with this packet // if it comes from a known source we should keep that node alive diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 6ebe30c930..93be4bcfc2 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -14,7 +14,9 @@ #include #include +#include #include +#include #ifndef _WIN32 #include // not on windows, not needed for mac or windows @@ -34,6 +36,7 @@ #include "DomainHandler.h" #include "Node.h" +#include "PacketHeaders.h" #include "UUIDHasher.h" const int MAX_PACKET_SIZE = 1450; @@ -76,6 +79,8 @@ namespace PingType { const PingType_t Symmetric = 3; } +typedef std::map PacketTypeSequenceMap; + class LimitedNodeList : public QObject, public Dependency { Q_OBJECT SINGLETON_DEPENDENCY @@ -224,8 +229,11 @@ protected: LimitedNodeList(LimitedNodeList const&); // Don't implement, needed to avoid copies of singleton void operator=(LimitedNodeList const&); // Don't implement, needed to avoid copies of singleton - qint64 writeDatagram(const QByteArray& datagram, const HifiSockAddr& destinationSockAddr, + qint64 writeDatagram(const QByteArray& datagram, + const HifiSockAddr& destinationSockAddr, const QUuid& connectionSecret); + + PacketSequenceNumber getNextSequenceNumberForPacket(const QUuid& nodeUUID, PacketType packetType); void changeSocketBufferSizes(int numBytes); @@ -247,6 +255,8 @@ protected: QElapsedTimer _packetStatTimer; bool _thisNodeCanAdjustLocks; bool _thisNodeCanRez; + + std::unordered_map _packetSequenceNumbers; template void eachNodeHashIterator(IteratorLambda functor) { diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index a9ccec34bb..f7c43fffb9 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -45,8 +45,8 @@ int packArithmeticallyCodedValue(int value, char* destination) { } } -PacketVersion versionForPacketType(PacketType type) { - switch (type) { +PacketVersion versionForPacketType(PacketType packetType) { + switch (packetType) { case PacketTypeMicrophoneAudioNoEcho: case PacketTypeMicrophoneAudioWithEcho: return 2; @@ -86,8 +86,8 @@ PacketVersion versionForPacketType(PacketType type) { #define PACKET_TYPE_NAME_LOOKUP(x) case x: return QString(#x); -QString nameForPacketType(PacketType type) { - switch (type) { +QString nameForPacketType(PacketType packetType) { + switch (packetType) { PACKET_TYPE_NAME_LOOKUP(PacketTypeUnknown); PACKET_TYPE_NAME_LOOKUP(PacketTypeStunResponse); PACKET_TYPE_NAME_LOOKUP(PacketTypeDomainList); @@ -132,30 +132,30 @@ QString nameForPacketType(PacketType type) { PACKET_TYPE_NAME_LOOKUP(PacketTypeUnverifiedPing); PACKET_TYPE_NAME_LOOKUP(PacketTypeUnverifiedPingReply); default: - return QString("Type: ") + QString::number((int)type); + return QString("Type: ") + QString::number((int)packetType); } return QString("unexpected"); } -QByteArray byteArrayWithPopulatedHeader(PacketType type, const QUuid& connectionUUID) { +QByteArray byteArrayWithPopulatedHeader(PacketType packetType, const QUuid& connectionUUID) { QByteArray freshByteArray(MAX_PACKET_HEADER_BYTES, 0); - freshByteArray.resize(populatePacketHeader(freshByteArray, type, connectionUUID)); + freshByteArray.resize(populatePacketHeader(freshByteArray, packetType, connectionUUID)); return freshByteArray; } -int populatePacketHeader(QByteArray& packet, PacketType type, const QUuid& connectionUUID) { - if (packet.size() < numBytesForPacketHeaderGivenPacketType(type)) { - packet.resize(numBytesForPacketHeaderGivenPacketType(type)); +int populatePacketHeader(QByteArray& packet, PacketType packetType, const QUuid& connectionUUID) { + if (packet.size() < numBytesForPacketHeaderGivenPacketType(packetType)) { + packet.resize(numBytesForPacketHeaderGivenPacketType(packetType)); } - return populatePacketHeader(packet.data(), type, connectionUUID); + return populatePacketHeader(packet.data(), packetType, connectionUUID); } -int populatePacketHeader(char* packet, PacketType type, const QUuid& connectionUUID) { - int numTypeBytes = packArithmeticallyCodedValue(type, packet); - packet[numTypeBytes] = versionForPacketType(type); +int populatePacketHeader(char* packet, PacketType packetType, const QUuid& connectionUUID) { + int numTypeBytes = packArithmeticallyCodedValue(packetType, packet); + packet[numTypeBytes] = versionForPacketType(packetType); char* position = packet + numTypeBytes + sizeof(PacketVersion); @@ -165,38 +165,46 @@ int populatePacketHeader(char* packet, PacketType type, const QUuid& connectionU memcpy(position, rfcUUID.constData(), NUM_BYTES_RFC4122_UUID); position += NUM_BYTES_RFC4122_UUID; - if (!NON_VERIFIED_PACKETS.contains(type)) { + if (!NON_VERIFIED_PACKETS.contains(packetType)) { // pack 16 bytes of zeros where the md5 hash will be placed once data is packed memset(position, 0, NUM_BYTES_MD5_HASH); position += NUM_BYTES_MD5_HASH; } - + + if (!SEQUENCE_NUMBERED_PACKETS.contains(packetType)) { + // Pack zeros for the number of bytes that the sequence number requires. + // The LimitedNodeList will handle packing in the sequence number when sending out the packet. + memset(position, 0, sizeof(PacketSequenceNumber)); + position += sizeof(PacketSequenceNumber); + } + // return the number of bytes written for pointer pushing return position - packet; } int numBytesForPacketHeader(const QByteArray& packet) { - // returns the number of bytes used for the type, version, and UUID - return numBytesArithmeticCodingFromBuffer(packet.data()) - + numHashBytesInPacketHeaderGivenPacketType(packetTypeForPacket(packet)) - + NUM_STATIC_HEADER_BYTES; + PacketType packetType = packetTypeForPacket(packet); + return numBytesForPacketHeaderGivenPacketType(packetType); } int numBytesForPacketHeader(const char* packet) { - // returns the number of bytes used for the type, version, and UUID - return numBytesArithmeticCodingFromBuffer(packet) - + numHashBytesInPacketHeaderGivenPacketType(packetTypeForPacket(packet)) + PacketType packetType = packetTypeForPacket(packet); + return numBytesForPacketHeaderGivenPacketType(packetType); +} + +int numBytesForPacketHeaderGivenPacketType(PacketType packetType) { + return (int) ceilf((float) packetType / 255) + + numHashBytesForType(packetType) + + numSequenceNumberBytesForType(packetType) + NUM_STATIC_HEADER_BYTES; } -int numBytesForPacketHeaderGivenPacketType(PacketType type) { - return (int) ceilf((float)type / 255) - + numHashBytesInPacketHeaderGivenPacketType(type) - + NUM_STATIC_HEADER_BYTES; +int numHashBytesForType(PacketType packetType) { + return (NON_VERIFIED_PACKETS.contains(packetType) ? 0 : NUM_BYTES_MD5_HASH); } -int numHashBytesInPacketHeaderGivenPacketType(PacketType type) { - return (NON_VERIFIED_PACKETS.contains(type) ? 0 : NUM_BYTES_MD5_HASH); +int numSequenceNumberBytesForType(PacketType packetType) { + return (SEQUENCE_NUMBERED_PACKETS.contains(packetType) ? sizeof(PacketSequenceNumber) : 0); } QUuid uuidFromPacketHeader(const QByteArray& packet) { @@ -204,8 +212,18 @@ QUuid uuidFromPacketHeader(const QByteArray& packet) { NUM_BYTES_RFC4122_UUID)); } +int hashOffsetForPacketType(PacketType packetType) { + return numBytesForPacketHeaderGivenPacketType(packetType) + - (SEQUENCE_NUMBERED_PACKETS.contains(packetType) ? sizeof(PacketSequenceNumber) : 0) + - NUM_BYTES_RFC4122_UUID; +} + +int sequenceNumberOffsetForPacketType(PacketType packetType) { + return numBytesForPacketHeaderGivenPacketType(packetType) - sizeof(PacketSequenceNumber); +} + QByteArray hashFromPacketHeader(const QByteArray& packet) { - return packet.mid(numBytesForPacketHeader(packet) - NUM_BYTES_MD5_HASH, NUM_BYTES_MD5_HASH); + return packet.mid(hashOffsetForPacketType(packetTypeForPacket(packet)), NUM_BYTES_MD5_HASH); } QByteArray hashForPacketAndConnectionUUID(const QByteArray& packet, const QUuid& connectionUUID) { @@ -213,9 +231,25 @@ QByteArray hashForPacketAndConnectionUUID(const QByteArray& packet, const QUuid& QCryptographicHash::Md5); } -void replaceHashInPacketGivenConnectionUUID(QByteArray& packet, const QUuid& connectionUUID) { - packet.replace(numBytesForPacketHeader(packet) - NUM_BYTES_MD5_HASH, NUM_BYTES_MD5_HASH, - hashForPacketAndConnectionUUID(packet, connectionUUID)); +void replaceHashInPacketGivenType(QByteArray& packet, PacketType packetType, const QUuid& connectionUUID) { + packet.replace(hashOffsetForPacketType(packetType), NUM_BYTES_MD5_HASH, + hashForPacketAndConnectionUUID(packet, connectionUUID)); +} + +void replaceSequenceNumberInPacketGivenType(QByteArray& packet, PacketType packetType, PacketSequenceNumber sequenceNumber) { + packet.replace(sequenceNumberOffsetForPacketType(packetType), + sizeof(PacketTypeSequenceMap), reinterpret_cast(&sequenceNumber)); +} + +void replaceHashAndSequenceNumberInPacketGivenType(QByteArray& packet, PacketType packetType, + const QUuid& connectionUUID, PacketSequenceNumber sequenceNumber) { + replaceHashInPacketGivenType(packet, packetType, connectionUUID); + replaceSequenceNumberInPacketGivenType(packet, packetType, sequenceNumber); +} + + +void replaceHashAndSequenceNumberInPacket(QByteArray& packet, const QUuid& connectionUUID, PacketSequenceNumber sequenceNumber) { + replaceHashAndSequenceNumberInPacketGivenType(packet, packetTypeForPacket(packet), connectionUUID, sequenceNumber); } PacketType packetTypeForPacket(const QByteArray& packet) { diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index 7b12b1a089..dc80feed3c 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -12,14 +12,16 @@ #ifndef hifi_PacketHeaders_h #define hifi_PacketHeaders_h +#include + #include #include #include #include "UUID.h" -// NOTE: if adding a new packet type, you can replace one marked usable or add at the end -// NOTE: if you want the name of the packet type to be available for debugging or logging, update nameForPacketType() as well +// NOTE: if adding a new packet packetType, you can replace one marked usable or add at the end +// NOTE: if you want the name of the packet packetType to be available for debugging or logging, update nameForPacketType() as well enum PacketType { PacketTypeUnknown, // 0 PacketTypeStunResponse, @@ -78,6 +80,7 @@ enum PacketType { }; typedef char PacketVersion; +typedef uint16_t PacketSequenceNumber; const QSet NON_VERIFIED_PACKETS = QSet() << PacketTypeDomainServerRequireDTLS << PacketTypeDomainConnectRequest @@ -88,33 +91,51 @@ const QSet NON_VERIFIED_PACKETS = QSet() << PacketTypeIceServerHeartbeat << PacketTypeIceServerHeartbeatResponse << PacketTypeUnverifiedPing << PacketTypeUnverifiedPingReply << PacketTypeStopNode; +const QSet SEQUENCE_NUMBERED_PACKETS = QSet() + << PacketTypeAvatarData; + const int NUM_BYTES_MD5_HASH = 16; const int NUM_STATIC_HEADER_BYTES = sizeof(PacketVersion) + NUM_BYTES_RFC4122_UUID; const int MAX_PACKET_HEADER_BYTES = sizeof(PacketType) + NUM_BYTES_MD5_HASH + NUM_STATIC_HEADER_BYTES; -PacketVersion versionForPacketType(PacketType type); -QString nameForPacketType(PacketType type); +PacketType packetTypeForPacket(const QByteArray& packet); +PacketType packetTypeForPacket(const char* packet); + +PacketVersion versionForPacketType(PacketType packetType); +QString nameForPacketType(PacketType packetType); const QUuid nullUUID = QUuid(); -QByteArray byteArrayWithPopulatedHeader(PacketType type, const QUuid& connectionUUID = nullUUID); -int populatePacketHeader(QByteArray& packet, PacketType type, const QUuid& connectionUUID = nullUUID); -int populatePacketHeader(char* packet, PacketType type, const QUuid& connectionUUID = nullUUID); +QByteArray byteArrayWithPopulatedHeader(PacketType packetType, const QUuid& connectionUUID = nullUUID); +int populatePacketHeader(QByteArray& packet, PacketType packetType, const QUuid& connectionUUID = nullUUID); +int populatePacketHeader(char* packet, PacketType packetType, const QUuid& connectionUUID = nullUUID); -int numHashBytesInPacketHeaderGivenPacketType(PacketType type); +int numHashBytesForType(PacketType packetType); +int numSequenceNumberBytesForType(PacketType packetType); int numBytesForPacketHeader(const QByteArray& packet); int numBytesForPacketHeader(const char* packet); -int numBytesForPacketHeaderGivenPacketType(PacketType type); +int numBytesForPacketHeaderGivenPacketType(PacketType packetType); QUuid uuidFromPacketHeader(const QByteArray& packet); +int hashOffsetForPacketType(PacketType packetType); +int sequenceNumberOffsetForPacketType(PacketType packetType); + QByteArray hashFromPacketHeader(const QByteArray& packet); QByteArray hashForPacketAndConnectionUUID(const QByteArray& packet, const QUuid& connectionUUID); -void replaceHashInPacketGivenConnectionUUID(QByteArray& packet, const QUuid& connectionUUID); -PacketType packetTypeForPacket(const QByteArray& packet); -PacketType packetTypeForPacket(const char* packet); +void replaceHashInPacketGivenType(QByteArray& packet, PacketType packetType, const QUuid& connectionUUID); +void replaceHashInPacket(QByteArray& packet, const QUuid& connectionUUID) + { replaceHashInPacketGivenType(packet, packetTypeForPacket(packet), connectionUUID); } + +void replaceSequenceNumberInPacketGivenType(QByteArray& packet, PacketType packetType, PacketSequenceNumber sequenceNumber); +void replaceSequenceNumberInPacket(QByteArray& packet, PacketSequenceNumber sequenceNumber) + { replaceSequenceNumberInPacketGivenType(packet, packetTypeForPacket(packet), sequenceNumber); } + +void replaceHashAndSequenceNumberInPacketGivenType(QByteArray& packet, PacketType packetType, + const QUuid& connectionUUID, PacketSequenceNumber sequenceNumber); +void replaceHashAndSequenceNumberInPacket(QByteArray& packet, const QUuid& connectionUUID, PacketSequenceNumber sequenceNumber); int arithmeticCodingValueFromBuffer(const char* checkValue); int numBytesArithmeticCodingFromBuffer(const char* checkValue); From 6b3cf1ba4a5980570e8e835f44f4fa79b73fcbf9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 5 May 2015 12:19:42 -0700 Subject: [PATCH 02/39] remove dependency of PacketHeaders on NodeList --- .../src/AssignmentClientMonitor.cpp | 6 +-- assignment-client/src/audio/AudioMixer.cpp | 13 +++--- .../src/audio/AudioMixerClientData.cpp | 2 +- assignment-client/src/avatars/AvatarMixer.cpp | 15 +++---- .../src/entities/EntityServer.cpp | 6 ++- .../octree/OctreeInboundPacketProcessor.cpp | 6 ++- .../src/octree/OctreeQueryNode.cpp | 4 +- domain-server/src/DomainServer.cpp | 43 +++++++++---------- ice-server/src/IceServer.cpp | 4 +- interface/src/Application.cpp | 4 +- interface/src/avatar/MyAvatar.cpp | 5 ++- libraries/audio-client/src/AudioClient.cpp | 11 ++--- libraries/audio-client/src/AudioIOStats.cpp | 7 +-- libraries/audio/src/AudioInjector.cpp | 5 ++- libraries/avatars/src/AvatarData.cpp | 18 +++++--- libraries/entities/src/EntityTree.cpp | 3 +- libraries/networking/src/LimitedNodeList.cpp | 13 +++--- libraries/networking/src/LimitedNodeList.h | 7 +++ libraries/networking/src/NodeList.cpp | 2 +- libraries/networking/src/PacketHeaders.cpp | 30 +++++++------ libraries/networking/src/PacketHeaders.h | 14 +++--- libraries/octree/src/JurisdictionListener.cpp | 7 ++- libraries/octree/src/JurisdictionMap.cpp | 10 +++-- .../octree/src/OctreeEditPacketSender.cpp | 3 +- libraries/octree/src/OctreeHeadlessViewer.cpp | 2 +- libraries/octree/src/OctreeSceneStats.cpp | 3 +- libraries/script-engine/src/ScriptEngine.cpp | 8 ++-- 27 files changed, 144 insertions(+), 107 deletions(-) diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 12f5abc796..4157e55754 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -88,7 +88,7 @@ void AssignmentClientMonitor::stopChildProcesses() { nodeList->eachNode([&](const SharedNodePointer& node) { qDebug() << "asking child" << node->getUUID() << "to exit."; node->activateLocalSocket(); - QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); + QByteArray diePacket = nodeList->byteArrayWithPopulatedHeader(PacketTypeStopNode); nodeList->writeUnverifiedDatagram(diePacket, *node->getActiveSocket()); }); @@ -193,7 +193,7 @@ void AssignmentClientMonitor::checkSpares() { qDebug() << "asking child" << aSpareId << "to exit."; SharedNodePointer childNode = nodeList->nodeWithUUID(aSpareId); childNode->activateLocalSocket(); - QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); + QByteArray diePacket = nodeList->byteArrayWithPopulatedHeader(PacketTypeStopNode); nodeList->writeUnverifiedDatagram(diePacket, childNode); } } @@ -229,7 +229,7 @@ void AssignmentClientMonitor::readPendingDatagrams() { } else { // tell unknown assignment-client child to exit. qDebug() << "asking unknown child to exit."; - QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); + QByteArray diePacket = nodeList->byteArrayWithPopulatedHeader(PacketTypeStopNode); nodeList->writeUnverifiedDatagram(diePacket, senderSockAddr); } } diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 94439cb18b..a9c0e5ddf2 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -514,7 +514,8 @@ void AudioMixer::sendAudioEnvironmentPacket(SharedNodePointer node) { bool sendData = dataChanged || (randFloat() < CHANCE_OF_SEND); if (sendData) { - int numBytesEnvPacketHeader = populatePacketHeader(clientEnvBuffer, PacketTypeAudioEnvironment); + auto nodeList = DependencyManager::get(); + int numBytesEnvPacketHeader = nodeList->populatePacketHeader(clientEnvBuffer, PacketTypeAudioEnvironment); char* envDataAt = clientEnvBuffer + numBytesEnvPacketHeader; unsigned char bitset = 0; @@ -531,7 +532,7 @@ void AudioMixer::sendAudioEnvironmentPacket(SharedNodePointer node) { memcpy(envDataAt, &wetLevel, sizeof(float)); envDataAt += sizeof(float); } - DependencyManager::get()->writeDatagram(clientEnvBuffer, envDataAt - clientEnvBuffer, node); + nodeList->writeDatagram(clientEnvBuffer, envDataAt - clientEnvBuffer, node); } } @@ -552,7 +553,7 @@ void AudioMixer::readPendingDatagram(const QByteArray& receivedPacket, const Hif SharedNodePointer sendingNode = nodeList->sendingNodeForPacket(receivedPacket); if (sendingNode->getCanAdjustLocks()) { QByteArray packet = receivedPacket; - populatePacketHeader(packet, PacketTypeMuteEnvironment); + nodeList->populatePacketHeader(packet, PacketTypeMuteEnvironment); nodeList->eachNode([&](const SharedNodePointer& node){ if (node->getType() == NodeType::Agent && node->getActiveSocket() && @@ -794,7 +795,7 @@ void AudioMixer::run() { // if the stream should be muted, send mute packet if (nodeData->getAvatarAudioStream() && shouldMute(nodeData->getAvatarAudioStream()->getQuietestFrameLoudness())) { - QByteArray packet = byteArrayWithPopulatedHeader(PacketTypeNoisyMute); + QByteArray packet = nodeList->byteArrayWithPopulatedHeader(PacketTypeNoisyMute); nodeList->writeDatagram(packet, node); } @@ -806,7 +807,7 @@ void AudioMixer::run() { char* mixDataAt; if (streamsMixed > 0) { // pack header - int numBytesMixPacketHeader = populatePacketHeader(clientMixBuffer, PacketTypeMixedAudio); + int numBytesMixPacketHeader = nodeList->populatePacketHeader(clientMixBuffer, PacketTypeMixedAudio); mixDataAt = clientMixBuffer + numBytesMixPacketHeader; // pack sequence number @@ -819,7 +820,7 @@ void AudioMixer::run() { mixDataAt += AudioConstants::NETWORK_FRAME_BYTES_STEREO; } else { // pack header - int numBytesPacketHeader = populatePacketHeader(clientMixBuffer, PacketTypeSilentAudioFrame); + int numBytesPacketHeader = nodeList->populatePacketHeader(clientMixBuffer, PacketTypeSilentAudioFrame); mixDataAt = clientMixBuffer + numBytesPacketHeader; // pack sequence number diff --git a/assignment-client/src/audio/AudioMixerClientData.cpp b/assignment-client/src/audio/AudioMixerClientData.cpp index 4db5611bb5..8848758f86 100644 --- a/assignment-client/src/audio/AudioMixerClientData.cpp +++ b/assignment-client/src/audio/AudioMixerClientData.cpp @@ -157,7 +157,7 @@ void AudioMixerClientData::sendAudioStreamStatsPackets(const SharedNodePointer& quint8 appendFlag = 0; // pack header - int numBytesPacketHeader = populatePacketHeader(packet, PacketTypeAudioStreamStats); + int numBytesPacketHeader = nodeList->populatePacketHeader(packet, PacketTypeAudioStreamStats); char* headerEndAt = packet + numBytesPacketHeader; // calculate how many stream stat structs we can fit in each packet diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 961cbecebb..99ae98fb14 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -129,10 +129,9 @@ void AvatarMixer::broadcastAvatarData() { static QByteArray mixedAvatarByteArray; - int numPacketHeaderBytes = populatePacketHeader(mixedAvatarByteArray, PacketTypeBulkAvatarData); - auto nodeList = DependencyManager::get(); - + int numPacketHeaderBytes = nodeList->populatePacketHeader(mixedAvatarByteArray, PacketTypeBulkAvatarData); + // setup for distributed random floating point values std::random_device randomDevice; std::mt19937 generator(randomDevice()); @@ -287,7 +286,7 @@ void AvatarMixer::broadcastAvatarData() { && (forceSend || otherNodeData->getBillboardChangeTimestamp() > _lastFrameTimestamp || randFloat() < BILLBOARD_AND_IDENTITY_SEND_PROBABILITY)) { - QByteArray billboardPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarBillboard); + QByteArray billboardPacket = nodeList->byteArrayWithPopulatedHeader(PacketTypeAvatarBillboard); billboardPacket.append(otherNode->getUUID().toRfc4122()); billboardPacket.append(otherNodeData->getAvatar().getBillboard()); @@ -301,7 +300,7 @@ void AvatarMixer::broadcastAvatarData() { || otherNodeData->getIdentityChangeTimestamp() > _lastFrameTimestamp || randFloat() < BILLBOARD_AND_IDENTITY_SEND_PROBABILITY)) { - QByteArray identityPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarIdentity); + QByteArray identityPacket = nodeList->byteArrayWithPopulatedHeader(PacketTypeAvatarIdentity); QByteArray individualData = otherNodeData->getAvatar().identityByteArray(); individualData.replace(0, NUM_BYTES_RFC4122_UUID, otherNode->getUUID().toRfc4122()); @@ -334,13 +333,13 @@ void AvatarMixer::broadcastAvatarData() { void AvatarMixer::nodeKilled(SharedNodePointer killedNode) { if (killedNode->getType() == NodeType::Agent && killedNode->getLinkedData()) { + auto nodeList = DependencyManager::get(); // this was an avatar we were sending to other people // send a kill packet for it to our other nodes - QByteArray killPacket = byteArrayWithPopulatedHeader(PacketTypeKillAvatar); + QByteArray killPacket = nodeList->byteArrayWithPopulatedHeader(PacketTypeKillAvatar); killPacket += killedNode->getUUID().toRfc4122(); - DependencyManager::get()->broadcastToNodes(killPacket, - NodeSet() << NodeType::Agent); + nodeList->broadcastToNodes(killPacket, NodeSet() << NodeType::Agent); } } diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index bb5042f4b4..0f5332192a 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -64,7 +64,9 @@ void EntityServer::entityCreated(const EntityItem& newEntity, const SharedNodePo unsigned char outputBuffer[MAX_PACKET_SIZE]; unsigned char* copyAt = outputBuffer; - int numBytesPacketHeader = populatePacketHeader(reinterpret_cast(outputBuffer), PacketTypeEntityAddResponse); + auto nodeList = DependencyManager::get(); + + int numBytesPacketHeader = nodeList->populatePacketHeader(reinterpret_cast(outputBuffer), PacketTypeEntityAddResponse); int packetLength = numBytesPacketHeader; copyAt += numBytesPacketHeader; @@ -81,7 +83,7 @@ void EntityServer::entityCreated(const EntityItem& newEntity, const SharedNodePo copyAt += sizeof(entityID); packetLength += sizeof(entityID); - DependencyManager::get()->writeDatagram((char*) outputBuffer, packetLength, senderNode); + nodeList->writeDatagram((char*) outputBuffer, packetLength, senderNode); } diff --git a/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp b/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp index f6ab12f421..28506b033e 100644 --- a/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp +++ b/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp @@ -277,9 +277,11 @@ int OctreeInboundPacketProcessor::sendNackPackets() { char* dataAt = packet; int bytesRemaining = MAX_PACKET_SIZE; + + auto nodeList = DependencyManager::get(); // pack header - int numBytesPacketHeader = populatePacketHeader(packet, _myServer->getMyEditNackType()); + int numBytesPacketHeader = nodeList->populatePacketHeader(packet, _myServer->getMyEditNackType()); dataAt += numBytesPacketHeader; bytesRemaining -= numBytesPacketHeader; @@ -301,7 +303,7 @@ int OctreeInboundPacketProcessor::sendNackPackets() { numSequenceNumbersAvailable -= numSequenceNumbers; // send it - DependencyManager::get()->writeUnverifiedDatagram(packet, dataAt - packet, destinationNode); + nodeList->writeUnverifiedDatagram(packet, dataAt - packet, destinationNode); packetsSent++; qDebug() << "NACK Sent back to editor/client... destinationNode=" << nodeUUID; diff --git a/assignment-client/src/octree/OctreeQueryNode.cpp b/assignment-client/src/octree/OctreeQueryNode.cpp index 2d8d8d357e..b6504863e0 100644 --- a/assignment-client/src/octree/OctreeQueryNode.cpp +++ b/assignment-client/src/octree/OctreeQueryNode.cpp @@ -189,7 +189,9 @@ void OctreeQueryNode::resetOctreePacket() { } _octreePacketAvailableBytes = MAX_PACKET_SIZE; - int numBytesPacketHeader = populatePacketHeader(reinterpret_cast(_octreePacket), _myPacketType); + int numBytesPacketHeader = DependencyManager::get()->populatePacketHeader(reinterpret_cast(_octreePacket), + _myPacketType); + _octreePacketAt = _octreePacket + numBytesPacketHeader; _octreePacketAvailableBytes -= numBytesPacketHeader; diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 6ee1d6c765..ea69b5bc95 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -619,10 +619,12 @@ void DomainServer::handleConnectRequest(const QByteArray& packet, const HifiSock packetStream >> nodeInterestList >> username >> usernameSignature; + auto limitedNodeList = DependencyManager::get(); + QString reason; if (!isAssignment && !shouldAllowConnectionFromNode(username, usernameSignature, senderSockAddr, reason)) { // this is an agent and we've decided we won't let them connect - send them a packet to deny connection - QByteArray connectionDeniedByteArray = byteArrayWithPopulatedHeader(PacketTypeDomainConnectionDenied); + QByteArray connectionDeniedByteArray = limitedNodeList->byteArrayWithPopulatedHeader(PacketTypeDomainConnectionDenied); QDataStream out(&connectionDeniedByteArray, QIODevice::WriteOnly | QIODevice::Append); out << reason; // tell client it has been refused. @@ -664,10 +666,9 @@ void DomainServer::handleConnectRequest(const QByteArray& packet, const HifiSock canRez = canAdjustLocks; } - SharedNodePointer newNode = - DependencyManager::get()->addOrUpdateNode(nodeUUID, nodeType, - publicSockAddr, localSockAddr, - canAdjustLocks, canRez); + SharedNodePointer newNode = limitedNodeList->addOrUpdateNode(nodeUUID, nodeType, + publicSockAddr, localSockAddr, + canAdjustLocks, canRez); // when the newNode is created the linked data is also created // if this was a static assignment set the UUID, set the sendingSockAddr DomainServerNodeData* nodeData = reinterpret_cast(newNode->getLinkedData()); @@ -926,8 +927,8 @@ NodeSet DomainServer::nodeInterestListFromPacket(const QByteArray& packet, int n void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const HifiSockAddr &senderSockAddr, const NodeSet& nodeInterestList) { - - QByteArray broadcastPacket = byteArrayWithPopulatedHeader(PacketTypeDomainList); + auto limitedNodeList = DependencyManager::get(); + QByteArray broadcastPacket = limitedNodeList->byteArrayWithPopulatedHeader(PacketTypeDomainList); // always send the node their own UUID back QDataStream broadcastDataStream(&broadcastPacket, QIODevice::Append); @@ -939,8 +940,6 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif DomainServerNodeData* nodeData = reinterpret_cast(node->getLinkedData()); - auto nodeList = DependencyManager::get(); - // if we've established a connection via ICE with this peer, use that socket // otherwise just try to reply back to them on their sending socket (although that may not work) HifiSockAddr destinationSockAddr = _connectedICEPeers.value(node->getUUID()); @@ -955,7 +954,7 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif if (nodeData->isAuthenticated()) { // if this authenticated node has any interest types, send back those nodes as well - nodeList->eachNode([&](const SharedNodePointer& otherNode){ + limitedNodeList->eachNode([&](const SharedNodePointer& otherNode){ // reset our nodeByteArray and nodeDataStream QByteArray nodeByteArray; QDataStream nodeDataStream(&nodeByteArray, QIODevice::Append); @@ -986,7 +985,7 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif // we need to break here and start a new packet // so send the current one - nodeList->writeDatagram(broadcastPacket, node, senderSockAddr); + limitedNodeList->writeDatagram(broadcastPacket, node, senderSockAddr); // reset the broadcastPacket structure broadcastPacket.resize(numBroadcastPacketLeadBytes); @@ -1001,24 +1000,24 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif } // always write the last broadcastPacket - nodeList->writeDatagram(broadcastPacket, node, senderSockAddr); + limitedNodeList->writeDatagram(broadcastPacket, node, senderSockAddr); } void DomainServer::readAvailableDatagrams() { - auto nodeList = DependencyManager::get(); + auto limitedNodeList = DependencyManager::get(); HifiSockAddr senderSockAddr; QByteArray receivedPacket; - static QByteArray assignmentPacket = byteArrayWithPopulatedHeader(PacketTypeCreateAssignment); + static QByteArray assignmentPacket = limitedNodeList->byteArrayWithPopulatedHeader(PacketTypeCreateAssignment); static int numAssignmentPacketHeaderBytes = assignmentPacket.size(); - while (nodeList->getNodeSocket().hasPendingDatagrams()) { - receivedPacket.resize(nodeList->getNodeSocket().pendingDatagramSize()); - nodeList->getNodeSocket().readDatagram(receivedPacket.data(), receivedPacket.size(), + while (limitedNodeList->getNodeSocket().hasPendingDatagrams()) { + receivedPacket.resize(limitedNodeList->getNodeSocket().pendingDatagramSize()); + limitedNodeList->getNodeSocket().readDatagram(receivedPacket.data(), receivedPacket.size(), senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer()); if (packetTypeForPacket(receivedPacket) == PacketTypeRequestAssignment - && nodeList->packetVersionAndHashMatch(receivedPacket)) { + && limitedNodeList->packetVersionAndHashMatch(receivedPacket)) { // construct the requested assignment from the packet data Assignment requestAssignment(receivedPacket); @@ -1059,7 +1058,7 @@ void DomainServer::readAvailableDatagrams() { assignmentStream << uniqueAssignment; - nodeList->getNodeSocket().writeDatagram(assignmentPacket, + limitedNodeList->getNodeSocket().writeDatagram(assignmentPacket, senderSockAddr.getAddress(), senderSockAddr.getPort()); // add the information for that deployed assignment to the hash of pending assigned nodes @@ -1081,16 +1080,16 @@ void DomainServer::readAvailableDatagrams() { processDatagram(receivedPacket, senderSockAddr); } else { // we're using DTLS, so tell the sender to get back to us using DTLS - static QByteArray dtlsRequiredPacket = byteArrayWithPopulatedHeader(PacketTypeDomainServerRequireDTLS); + static QByteArray dtlsRequiredPacket = limitedNodeList->byteArrayWithPopulatedHeader(PacketTypeDomainServerRequireDTLS); static int numBytesDTLSHeader = numBytesForPacketHeaderGivenPacketType(PacketTypeDomainServerRequireDTLS); if (dtlsRequiredPacket.size() == numBytesDTLSHeader) { // pack the port that we accept DTLS traffic on - unsigned short dtlsPort = nodeList->getDTLSSocket().localPort(); + unsigned short dtlsPort = limitedNodeList->getDTLSSocket().localPort(); dtlsRequiredPacket.replace(numBytesDTLSHeader, sizeof(dtlsPort), reinterpret_cast(&dtlsPort)); } - nodeList->writeUnverifiedDatagram(dtlsRequiredPacket, senderSockAddr); + limitedNodeList->writeUnverifiedDatagram(dtlsRequiredPacket, senderSockAddr); } } } diff --git a/ice-server/src/IceServer.cpp b/ice-server/src/IceServer.cpp index 77deb6125b..e72555cac1 100644 --- a/ice-server/src/IceServer.cpp +++ b/ice-server/src/IceServer.cpp @@ -117,7 +117,7 @@ void IceServer::sendHeartbeatResponse(const HifiSockAddr& destinationSockAddr, Q QSet::iterator peerID = connections.begin(); QByteArray outgoingPacket(MAX_PACKET_SIZE, 0); - int currentPacketSize = populatePacketHeader(outgoingPacket, PacketTypeIceServerHeartbeatResponse, _id); + int currentPacketSize = populatePacketHeaderWithUUID(outgoingPacket, PacketTypeIceServerHeartbeatResponse, _id); int numHeaderBytes = currentPacketSize; // go through the connections, sending packets containing connection information for those nodes @@ -136,7 +136,7 @@ void IceServer::sendHeartbeatResponse(const HifiSockAddr& destinationSockAddr, Q destinationSockAddr.getAddress(), destinationSockAddr.getPort()); // reset the packet size to our number of header bytes - currentPacketSize = populatePacketHeader(outgoingPacket, PacketTypeIceServerHeartbeatResponse, _id); + currentPacketSize = populatePacketHeaderWithUUID(outgoingPacket, PacketTypeIceServerHeartbeatResponse, _id); } // append the current peer bytes diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1447478b5f..24f232993f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2478,7 +2478,7 @@ int Application::sendNackPackets() { int bytesRemaining = MAX_PACKET_SIZE; // pack header - int numBytesPacketHeader = populatePacketHeader(packet, PacketTypeOctreeDataNack); + int numBytesPacketHeader = nodeList->populatePacketHeader(packet, PacketTypeOctreeDataNack); dataAt += numBytesPacketHeader; bytesRemaining -= numBytesPacketHeader; @@ -2672,7 +2672,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node unsigned char* endOfQueryPacket = queryPacket; // insert packet type/version and node UUID - endOfQueryPacket += populatePacketHeader(reinterpret_cast(endOfQueryPacket), packetType); + endOfQueryPacket += nodeList->populatePacketHeader(reinterpret_cast(endOfQueryPacket), packetType); // encode the query data... endOfQueryPacket += _octreeQuery.getBroadcastData(endOfQueryPacket); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 557d630ebf..0244446a81 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -846,8 +846,9 @@ int MyAvatar::parseDataAtOffset(const QByteArray& packet, int offset) { } void MyAvatar::sendKillAvatar() { - QByteArray killPacket = byteArrayWithPopulatedHeader(PacketTypeKillAvatar); - DependencyManager::get()->broadcastToNodes(killPacket, NodeSet() << NodeType::AvatarMixer); + auto nodeList = DependencyManager::get(); + QByteArray killPacket = nodeList->byteArrayWithPopulatedHeader(PacketTypeKillAvatar); + nodeList->broadcastToNodes(killPacket, NodeSet() << NodeType::AvatarMixer); } void MyAvatar::updateLookAtTargetAvatar() { diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index e581105cd2..10e2bc3bbf 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -837,7 +837,7 @@ void AudioClient::handleAudioInput() { } } - char* currentPacketPtr = audioDataPacket + populatePacketHeader(audioDataPacket, packetType); + char* currentPacketPtr = audioDataPacket + nodeList->populatePacketHeader(audioDataPacket, packetType); // pack sequence number memcpy(currentPacketPtr, &_outgoingAvatarAudioSequenceNumber, sizeof(quint16)); @@ -899,7 +899,9 @@ void AudioClient::processReceivedSamples(const QByteArray& inputBuffer, QByteArr } void AudioClient::sendMuteEnvironmentPacket() { - QByteArray mutePacket = byteArrayWithPopulatedHeader(PacketTypeMuteEnvironment); + auto nodeList = DependencyManager::get(); + + QByteArray mutePacket = nodeList->byteArrayWithPopulatedHeader(PacketTypeMuteEnvironment); int headerSize = mutePacket.size(); const float MUTE_RADIUS = 50; @@ -910,12 +912,11 @@ void AudioClient::sendMuteEnvironmentPacket() { memcpy(mutePacket.data() + headerSize + sizeof(glm::vec3), &MUTE_RADIUS, sizeof(float)); // grab our audio mixer from the NodeList, if it exists - auto nodelist = DependencyManager::get(); - SharedNodePointer audioMixer = nodelist->soloNodeOfType(NodeType::AudioMixer); + SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer); if (audioMixer) { // send off this mute packet - nodelist->writeDatagram(mutePacket, audioMixer); + nodeList->writeDatagram(mutePacket, audioMixer); } } diff --git a/libraries/audio-client/src/AudioIOStats.cpp b/libraries/audio-client/src/AudioIOStats.cpp index 88a1b96d4c..0a6c94671b 100644 --- a/libraries/audio-client/src/AudioIOStats.cpp +++ b/libraries/audio-client/src/AudioIOStats.cpp @@ -104,10 +104,12 @@ void AudioIOStats::sendDownstreamAudioStatsPacket() { // also, call _receivedAudioStream's per-second callback _receivedAudioStream->perSecondCallbackForUpdatingStats(); + auto nodeList = DependencyManager::get(); + char packet[MAX_PACKET_SIZE]; // pack header - int numBytesPacketHeader = populatePacketHeader(packet, PacketTypeAudioStreamStats); + int numBytesPacketHeader = nodeList->populatePacketHeader(packet, PacketTypeAudioStreamStats); char* dataAt = packet + numBytesPacketHeader; // pack append flag @@ -126,7 +128,6 @@ void AudioIOStats::sendDownstreamAudioStatsPacket() { dataAt += sizeof(AudioStreamStats); // send packet - auto nodeList = DependencyManager::get(); SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer); nodeList->writeDatagram(packet, dataAt - packet, audioMixer); -} \ No newline at end of file +} diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 26140b82c8..ae397ba97e 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -141,11 +141,13 @@ void AudioInjector::injectToMixer() { _currentSendPosition = 0; } + auto nodeList = DependencyManager::get(); + // make sure we actually have samples downloaded to inject if (_audioData.size()) { // setup the packet for injected audio - QByteArray injectAudioPacket = byteArrayWithPopulatedHeader(PacketTypeInjectAudio); + QByteArray injectAudioPacket = nodeList->byteArrayWithPopulatedHeader(PacketTypeInjectAudio); QDataStream packetStream(&injectAudioPacket, QIODevice::Append); // pack some placeholder sequence number for now @@ -226,7 +228,6 @@ void AudioInjector::injectToMixer() { _audioData.data() + _currentSendPosition, bytesToCopy); // grab our audio mixer from the NodeList, if it exists - auto nodeList = DependencyManager::get(); SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer); // send off this audio packet diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index f0e4eb118b..c7ab6dce2e 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -1077,25 +1077,31 @@ void AvatarData::setJointMappingsFromNetworkReply() { } void AvatarData::sendAvatarDataPacket() { - QByteArray dataPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarData); + auto nodeList = DependencyManager::get(); + + QByteArray dataPacket = nodeList->byteArrayWithPopulatedHeader(PacketTypeAvatarData); dataPacket.append(toByteArray()); - DependencyManager::get()->broadcastToNodes(dataPacket, NodeSet() << NodeType::AvatarMixer); + nodeList->broadcastToNodes(dataPacket, NodeSet() << NodeType::AvatarMixer); } void AvatarData::sendIdentityPacket() { - QByteArray identityPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarIdentity); + auto nodeList = DependencyManager::get(); + + QByteArray identityPacket = nodeList->byteArrayWithPopulatedHeader(PacketTypeAvatarIdentity); identityPacket.append(identityByteArray()); - DependencyManager::get()->broadcastToNodes(identityPacket, NodeSet() << NodeType::AvatarMixer); + nodeList->broadcastToNodes(identityPacket, NodeSet() << NodeType::AvatarMixer); } void AvatarData::sendBillboardPacket() { if (!_billboard.isEmpty()) { - QByteArray billboardPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarBillboard); + auto nodeList = DependencyManager::get(); + + QByteArray billboardPacket = nodeList->byteArrayWithPopulatedHeader(PacketTypeAvatarBillboard); billboardPacket.append(_billboard); - DependencyManager::get()->broadcastToNodes(billboardPacket, NodeSet() << NodeType::AvatarMixer); + nodeList->broadcastToNodes(billboardPacket, NodeSet() << NodeType::AvatarMixer); } } diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index f8f94f8d17..1d9cb25789 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -788,7 +788,8 @@ bool EntityTree::encodeEntitiesDeletedSince(OCTREE_PACKET_SEQUENCE sequenceNumbe bool hasMoreToSend = true; unsigned char* copyAt = outputBuffer; - size_t numBytesPacketHeader = populatePacketHeader(reinterpret_cast(outputBuffer), PacketTypeEntityErase); + size_t numBytesPacketHeader = DependencyManager::get()->populatePacketHeader(reinterpret_cast(outputBuffer), + PacketTypeEntityErase); copyAt += numBytesPacketHeader; outputLength = numBytesPacketHeader; diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index b125394103..0237121209 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "LimitedNodeList.h" + #include #include #include @@ -28,8 +30,6 @@ #include "AccountManager.h" #include "Assignment.h" #include "HifiSockAddr.h" -#include "LimitedNodeList.h" -#include "PacketHeaders.h" #include "UUID.h" #include "NetworkLogging.h" @@ -269,6 +269,7 @@ qint64 LimitedNodeList::writeDatagram(const QByteArray& datagram, // perform replacement of hash and optionally also sequence number in the header if (SEQUENCE_NUMBERED_PACKETS.contains(packetType)) { PacketSequenceNumber sequenceNumber = getNextSequenceNumberForPacket(destinationNode->getUUID(), packetType); + qDebug() << "Sequence number for this packet is" << sequenceNumber; replaceHashAndSequenceNumberInPacketGivenType(datagramCopy, packetType, destinationNode->getConnectionSecret(), sequenceNumber); @@ -481,8 +482,8 @@ unsigned LimitedNodeList::broadcastToNodes(const QByteArray& packet, const NodeS } QByteArray LimitedNodeList::constructPingPacket(PingType_t pingType, bool isVerified, const QUuid& packetHeaderID) { - QByteArray pingPacket = byteArrayWithPopulatedHeader(isVerified ? PacketTypePing : PacketTypeUnverifiedPing, - packetHeaderID); + QByteArray pingPacket = byteArrayWithUUIDPopulatedHeader(isVerified ? PacketTypePing : PacketTypeUnverifiedPing, + packetHeaderID); QDataStream packetStream(&pingPacket, QIODevice::Append); @@ -505,7 +506,7 @@ QByteArray LimitedNodeList::constructPingReplyPacket(const QByteArray& pingPacke PacketType replyType = (packetTypeForPacket(pingPacket) == PacketTypePing) ? PacketTypePingReply : PacketTypeUnverifiedPingReply; - QByteArray replyPacket = byteArrayWithPopulatedHeader(replyType, packetHeaderID); + QByteArray replyPacket = byteArrayWithUUIDPopulatedHeader(replyType, packetHeaderID); QDataStream packetStream(&replyPacket, QIODevice::Append); packetStream << typeFromOriginalPing << timeFromOriginalPing << usecTimestampNow(); @@ -695,7 +696,7 @@ void LimitedNodeList::sendHeartbeatToIceServer(const HifiSockAddr& iceServerSock headerID = _sessionUUID; } - QByteArray iceRequestByteArray = byteArrayWithPopulatedHeader(PacketTypeIceServerHeartbeat, headerID); + QByteArray iceRequestByteArray = byteArrayWithUUIDPopulatedHeader(PacketTypeIceServerHeartbeat, headerID); QDataStream iceDataStream(&iceRequestByteArray, QIODevice::Append); iceDataStream << _publicSockAddr << _localSockAddr; diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 93be4bcfc2..53bf6ea2d8 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -101,6 +101,13 @@ public: bool packetVersionAndHashMatch(const QByteArray& packet); + QByteArray byteArrayWithPopulatedHeader(PacketType packetType) + { return byteArrayWithUUIDPopulatedHeader(packetType, _sessionUUID); } + int populatePacketHeader(QByteArray& packet, PacketType packetType) + { return populatePacketHeaderWithUUID(packet, packetType, _sessionUUID); } + int populatePacketHeader(char* packet, PacketType packetType) + { return populatePacketHeaderWithUUID(packet, packetType, _sessionUUID); } + qint64 readDatagram(QByteArray& incomingPacket, QHostAddress* address, quint16 * port); qint64 writeDatagram(const QByteArray& datagram, const SharedNodePointer& destinationNode, diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 819c46cdf0..98cb0b1568 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -348,7 +348,7 @@ void NodeList::sendDomainServerCheckIn() { } } - QByteArray domainServerPacket = byteArrayWithPopulatedHeader(domainPacketType, packetUUID); + QByteArray domainServerPacket = byteArrayWithUUIDPopulatedHeader(domainPacketType, packetUUID); QDataStream packetStream(&domainServerPacket, QIODevice::Append); // pack our data to send to the domain-server diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index f7c43fffb9..8e3f47a47e 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -9,14 +9,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "PacketHeaders.h" + #include #include -#include "NodeList.h" - -#include "PacketHeaders.h" - int arithmeticCodingValueFromBuffer(const char* checkValue) { if (((uchar) *checkValue) < 255) { return *checkValue; @@ -139,29 +137,27 @@ QString nameForPacketType(PacketType packetType) { -QByteArray byteArrayWithPopulatedHeader(PacketType packetType, const QUuid& connectionUUID) { +QByteArray byteArrayWithUUIDPopulatedHeader(PacketType packetType, const QUuid& connectionUUID) { QByteArray freshByteArray(MAX_PACKET_HEADER_BYTES, 0); - freshByteArray.resize(populatePacketHeader(freshByteArray, packetType, connectionUUID)); + freshByteArray.resize(populatePacketHeaderWithUUID(freshByteArray, packetType, connectionUUID)); return freshByteArray; } -int populatePacketHeader(QByteArray& packet, PacketType packetType, const QUuid& connectionUUID) { +int populatePacketHeaderWithUUID(QByteArray& packet, PacketType packetType, const QUuid& connectionUUID) { if (packet.size() < numBytesForPacketHeaderGivenPacketType(packetType)) { packet.resize(numBytesForPacketHeaderGivenPacketType(packetType)); } - return populatePacketHeader(packet.data(), packetType, connectionUUID); + return populatePacketHeaderWithUUID(packet.data(), packetType, connectionUUID); } -int populatePacketHeader(char* packet, PacketType packetType, const QUuid& connectionUUID) { +int populatePacketHeaderWithUUID(char* packet, PacketType packetType, const QUuid& connectionUUID) { int numTypeBytes = packArithmeticallyCodedValue(packetType, packet); packet[numTypeBytes] = versionForPacketType(packetType); char* position = packet + numTypeBytes + sizeof(PacketVersion); - QUuid packUUID = connectionUUID.isNull() ? DependencyManager::get()->getSessionUUID() : connectionUUID; - - QByteArray rfcUUID = packUUID.toRfc4122(); + QByteArray rfcUUID = connectionUUID.toRfc4122(); memcpy(position, rfcUUID.constData(), NUM_BYTES_RFC4122_UUID); position += NUM_BYTES_RFC4122_UUID; @@ -236,11 +232,19 @@ void replaceHashInPacketGivenType(QByteArray& packet, PacketType packetType, con hashForPacketAndConnectionUUID(packet, connectionUUID)); } +void replaceHashInPacket(QByteArray& packet, const QUuid& connectionUUID) { + replaceHashInPacketGivenType(packet, packetTypeForPacket(packet), connectionUUID); +} + void replaceSequenceNumberInPacketGivenType(QByteArray& packet, PacketType packetType, PacketSequenceNumber sequenceNumber) { packet.replace(sequenceNumberOffsetForPacketType(packetType), - sizeof(PacketTypeSequenceMap), reinterpret_cast(&sequenceNumber)); + sizeof(PacketSequenceNumber), reinterpret_cast(&sequenceNumber)); } +void replaceSequenceNumberInPacket(QByteArray& packet, PacketSequenceNumber sequenceNumber) { + replaceSequenceNumberInPacketGivenType(packet, packetTypeForPacket(packet), sequenceNumber); +} + void replaceHashAndSequenceNumberInPacketGivenType(QByteArray& packet, PacketType packetType, const QUuid& connectionUUID, PacketSequenceNumber sequenceNumber) { replaceHashInPacketGivenType(packet, packetType, connectionUUID); diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index dc80feed3c..c1e397022e 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -12,6 +12,8 @@ #ifndef hifi_PacketHeaders_h #define hifi_PacketHeaders_h +#pragma once + #include #include @@ -106,9 +108,9 @@ QString nameForPacketType(PacketType packetType); const QUuid nullUUID = QUuid(); -QByteArray byteArrayWithPopulatedHeader(PacketType packetType, const QUuid& connectionUUID = nullUUID); -int populatePacketHeader(QByteArray& packet, PacketType packetType, const QUuid& connectionUUID = nullUUID); -int populatePacketHeader(char* packet, PacketType packetType, const QUuid& connectionUUID = nullUUID); +QByteArray byteArrayWithUUIDPopulatedHeader(PacketType packetType, const QUuid& connectionUUID); +int populatePacketHeaderWithUUID(QByteArray& packet, PacketType packetType, const QUuid& connectionUUID); +int populatePacketHeaderWithUUID(char* packet, PacketType packetType, const QUuid& connectionUUID); int numHashBytesForType(PacketType packetType); int numSequenceNumberBytesForType(PacketType packetType); @@ -126,12 +128,10 @@ QByteArray hashFromPacketHeader(const QByteArray& packet); QByteArray hashForPacketAndConnectionUUID(const QByteArray& packet, const QUuid& connectionUUID); void replaceHashInPacketGivenType(QByteArray& packet, PacketType packetType, const QUuid& connectionUUID); -void replaceHashInPacket(QByteArray& packet, const QUuid& connectionUUID) - { replaceHashInPacketGivenType(packet, packetTypeForPacket(packet), connectionUUID); } +void replaceHashInPacket(QByteArray& packet, const QUuid& connectionUUID); void replaceSequenceNumberInPacketGivenType(QByteArray& packet, PacketType packetType, PacketSequenceNumber sequenceNumber); -void replaceSequenceNumberInPacket(QByteArray& packet, PacketSequenceNumber sequenceNumber) - { replaceSequenceNumberInPacketGivenType(packet, packetTypeForPacket(packet), sequenceNumber); } +void replaceSequenceNumberInPacket(QByteArray& packet, PacketSequenceNumber sequenceNumber); void replaceHashAndSequenceNumberInPacketGivenType(QByteArray& packet, PacketType packetType, const QUuid& connectionUUID, PacketSequenceNumber sequenceNumber); diff --git a/libraries/octree/src/JurisdictionListener.cpp b/libraries/octree/src/JurisdictionListener.cpp index c050e0bffe..71c4feda96 100644 --- a/libraries/octree/src/JurisdictionListener.cpp +++ b/libraries/octree/src/JurisdictionListener.cpp @@ -35,10 +35,13 @@ void JurisdictionListener::nodeKilled(SharedNodePointer node) { bool JurisdictionListener::queueJurisdictionRequest() { static unsigned char buffer[MAX_PACKET_SIZE]; unsigned char* bufferOut = &buffer[0]; - int sizeOut = populatePacketHeader(reinterpret_cast(bufferOut), PacketTypeJurisdictionRequest); + + auto nodeList = DependencyManager::get(); + + int sizeOut = nodeList->populatePacketHeader(reinterpret_cast(bufferOut), PacketTypeJurisdictionRequest); int nodeCount = 0; - DependencyManager::get()->eachNode([&](const SharedNodePointer& node) { + nodeList->eachNode([&](const SharedNodePointer& node) { if (node->getType() == getNodeType() && node->getActiveSocket()) { _packetSender.queuePacketForSending(node, QByteArray(reinterpret_cast(bufferOut), sizeOut)); nodeCount++; diff --git a/libraries/octree/src/JurisdictionMap.cpp b/libraries/octree/src/JurisdictionMap.cpp index 79c1a96ccc..46e758cb42 100644 --- a/libraries/octree/src/JurisdictionMap.cpp +++ b/libraries/octree/src/JurisdictionMap.cpp @@ -14,6 +14,8 @@ #include #include +#include +#include #include #include @@ -268,8 +270,9 @@ bool JurisdictionMap::writeToFile(const char* filename) { int JurisdictionMap::packEmptyJurisdictionIntoMessage(NodeType_t type, unsigned char* destinationBuffer, int availableBytes) { unsigned char* bufferStart = destinationBuffer; - - int headerLength = populatePacketHeader(reinterpret_cast(destinationBuffer), PacketTypeJurisdiction); + + int headerLength = DependencyManager::get()->populatePacketHeader(reinterpret_cast(destinationBuffer), + PacketTypeJurisdiction); destinationBuffer += headerLength; // Pack the Node Type in first byte @@ -287,7 +290,8 @@ int JurisdictionMap::packEmptyJurisdictionIntoMessage(NodeType_t type, unsigned int JurisdictionMap::packIntoMessage(unsigned char* destinationBuffer, int availableBytes) { unsigned char* bufferStart = destinationBuffer; - int headerLength = populatePacketHeader(reinterpret_cast(destinationBuffer), PacketTypeJurisdiction); + int headerLength = DependencyManager::get()->populatePacketHeader(reinterpret_cast(destinationBuffer), + PacketTypeJurisdiction); destinationBuffer += headerLength; // Pack the Node Type in first byte diff --git a/libraries/octree/src/OctreeEditPacketSender.cpp b/libraries/octree/src/OctreeEditPacketSender.cpp index 65fbb0f983..9b1124a197 100644 --- a/libraries/octree/src/OctreeEditPacketSender.cpp +++ b/libraries/octree/src/OctreeEditPacketSender.cpp @@ -328,7 +328,8 @@ void OctreeEditPacketSender::releaseQueuedPacket(EditPacketBuffer& packetBuffer) } void OctreeEditPacketSender::initializePacket(EditPacketBuffer& packetBuffer, PacketType type, int nodeClockSkew) { - packetBuffer._currentSize = populatePacketHeader(reinterpret_cast(&packetBuffer._currentBuffer[0]), type); + packetBuffer._currentSize = + DependencyManager::get()->populatePacketHeader(reinterpret_cast(&packetBuffer._currentBuffer[0]), type); // skip over sequence number for now; will be packed when packet is ready to be sent out packetBuffer._currentSize += sizeof(quint16); diff --git a/libraries/octree/src/OctreeHeadlessViewer.cpp b/libraries/octree/src/OctreeHeadlessViewer.cpp index ea5c811ce1..63cd6d39a2 100644 --- a/libraries/octree/src/OctreeHeadlessViewer.cpp +++ b/libraries/octree/src/OctreeHeadlessViewer.cpp @@ -221,7 +221,7 @@ void OctreeHeadlessViewer::queryOctree() { unsigned char* endOfQueryPacket = queryPacket; // insert packet type/version and node UUID - endOfQueryPacket += populatePacketHeader(reinterpret_cast(endOfQueryPacket), packetType); + endOfQueryPacket += nodeList->populatePacketHeader(reinterpret_cast(endOfQueryPacket), packetType); // encode the query data... endOfQueryPacket += _octreeQuery.getBroadcastData(endOfQueryPacket); diff --git a/libraries/octree/src/OctreeSceneStats.cpp b/libraries/octree/src/OctreeSceneStats.cpp index c5a5678503..d12d4f1ba1 100644 --- a/libraries/octree/src/OctreeSceneStats.cpp +++ b/libraries/octree/src/OctreeSceneStats.cpp @@ -385,7 +385,8 @@ void OctreeSceneStats::childBitsRemoved(bool includesExistsBits, bool includesCo int OctreeSceneStats::packIntoMessage(unsigned char* destinationBuffer, int availableBytes) { unsigned char* bufferStart = destinationBuffer; - int headerLength = populatePacketHeader(reinterpret_cast(destinationBuffer), PacketTypeOctreeStats); + int headerLength = DependencyManager::get()->populatePacketHeader(reinterpret_cast(destinationBuffer), + PacketTypeOctreeStats); destinationBuffer += headerLength; memcpy(destinationBuffer, &_start, sizeof(_start)); diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index ac2c212001..f02ef3a549 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -493,7 +493,7 @@ void ScriptEngine::run() { / (1000 * 1000)) + 0.5); const int SCRIPT_AUDIO_BUFFER_BYTES = SCRIPT_AUDIO_BUFFER_SAMPLES * sizeof(int16_t); - QByteArray avatarPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarData); + QByteArray avatarPacket = nodeList->byteArrayWithPopulatedHeader(PacketTypeAvatarData); avatarPacket.append(_avatarData->toByteArray()); nodeList->broadcastToNodes(avatarPacket, NodeSet() << NodeType::AvatarMixer); @@ -534,9 +534,9 @@ void ScriptEngine::run() { } } - QByteArray audioPacket = byteArrayWithPopulatedHeader(silentFrame - ? PacketTypeSilentAudioFrame - : PacketTypeMicrophoneAudioNoEcho); + QByteArray audioPacket = nodeList->byteArrayWithPopulatedHeader(silentFrame + ? PacketTypeSilentAudioFrame + : PacketTypeMicrophoneAudioNoEcho); QDataStream packetStream(&audioPacket, QIODevice::Append); From a481c573153ace2abb995e2c359d81cd22eabe15 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 5 May 2015 12:44:47 -0700 Subject: [PATCH 03/39] fix for writeDatagram with hash and sequence number --- libraries/networking/src/LimitedNodeList.cpp | 13 +++++++++---- libraries/networking/src/NodeList.cpp | 4 ++-- libraries/networking/src/PacketHeaders.cpp | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 0237121209..61b98ffa44 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -278,7 +278,7 @@ qint64 LimitedNodeList::writeDatagram(const QByteArray& datagram, } emit dataSent(destinationNode->getType(), datagram.size()); - auto bytesWritten = writeDatagram(datagram, *destinationSockAddr, destinationNode->getConnectionSecret()); + auto bytesWritten = writeDatagram(datagramCopy, *destinationSockAddr, destinationNode->getConnectionSecret()); // Keep track of per-destination-node bandwidth destinationNode->recordBytesSent(bytesWritten); return bytesWritten; @@ -482,8 +482,11 @@ unsigned LimitedNodeList::broadcastToNodes(const QByteArray& packet, const NodeS } QByteArray LimitedNodeList::constructPingPacket(PingType_t pingType, bool isVerified, const QUuid& packetHeaderID) { + + QUuid packetUUID = packetHeaderID.isNull() ? _sessionUUID : packetHeaderID; + QByteArray pingPacket = byteArrayWithUUIDPopulatedHeader(isVerified ? PacketTypePing : PacketTypeUnverifiedPing, - packetHeaderID); + packetUUID); QDataStream packetStream(&pingPacket, QIODevice::Append); @@ -505,8 +508,10 @@ QByteArray LimitedNodeList::constructPingReplyPacket(const QByteArray& pingPacke PacketType replyType = (packetTypeForPacket(pingPacket) == PacketTypePing) ? PacketTypePingReply : PacketTypeUnverifiedPingReply; - - QByteArray replyPacket = byteArrayWithUUIDPopulatedHeader(replyType, packetHeaderID); + + QUuid packetUUID = packetHeaderID.isNull() ? _sessionUUID : packetHeaderID; + + QByteArray replyPacket = byteArrayWithUUIDPopulatedHeader(replyType, packetUUID); QDataStream packetStream(&replyPacket, QIODevice::Append); packetStream << typeFromOriginalPing << timeFromOriginalPing << usecTimestampNow(); diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 98cb0b1568..179f054e42 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -183,7 +183,7 @@ void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteAr } case PacketTypePingReply: { SharedNodePointer sendingNode = sendingNodeForPacket(packet); - + if (sendingNode) { sendingNode->setLastHeardMicrostamp(usecTimestampNow()); @@ -497,7 +497,7 @@ void NodeList::pingPunchForInactiveNode(const SharedNodePointer& node) { QByteArray publicPingPacket = constructPingPacket(PingType::Public); writeDatagram(publicPingPacket, node, node->getPublicSocket()); - + if (!node->getSymmetricSocket().isNull()) { QByteArray symmetricPingPacket = constructPingPacket(PingType::Symmetric); writeDatagram(symmetricPingPacket, node, node->getSymmetricSocket()); diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index 8e3f47a47e..b4fabc6340 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -167,7 +167,7 @@ int populatePacketHeaderWithUUID(char* packet, PacketType packetType, const QUui position += NUM_BYTES_MD5_HASH; } - if (!SEQUENCE_NUMBERED_PACKETS.contains(packetType)) { + if (SEQUENCE_NUMBERED_PACKETS.contains(packetType)) { // Pack zeros for the number of bytes that the sequence number requires. // The LimitedNodeList will handle packing in the sequence number when sending out the packet. memset(position, 0, sizeof(PacketSequenceNumber)); From 3887467048e0d9f37223b56bf0b71807a2211875 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 6 May 2015 10:41:24 -0700 Subject: [PATCH 04/39] store last broadcasted sequence number --- .../src/avatars/AvatarMixerClientData.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/assignment-client/src/avatars/AvatarMixerClientData.h b/assignment-client/src/avatars/AvatarMixerClientData.h index cccc5ee60f..d569a79e64 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.h +++ b/assignment-client/src/avatars/AvatarMixerClientData.h @@ -21,6 +21,7 @@ #include #include #include +#include #include const QString OUTBOUND_AVATAR_DATA_STATS_KEY = "outbound_av_data_kbps"; @@ -32,7 +33,10 @@ public: AvatarData& getAvatar() { return _avatar; } bool checkAndSetHasReceivedFirstPackets(); - + + PacketSequenceNumber getLastBroadcastSequenceNumber() const { return _lastBroadcastSequenceNumber; } + void setLastBroadcastSequenceNumber(PacketSequenceNumber sequenceNumber) { _lastBroadcastSequenceNumber = sequenceNumber; } + quint64 getBillboardChangeTimestamp() const { return _billboardChangeTimestamp; } void setBillboardChangeTimestamp(quint64 billboardChangeTimestamp) { _billboardChangeTimestamp = billboardChangeTimestamp; } @@ -61,13 +65,19 @@ public: void loadJSONStats(QJsonObject& jsonObject) const; private: AvatarData _avatar; + + PacketSequenceNumber _lastBroadcastSequenceNumber = 0; + bool _hasReceivedFirstPackets = false; quint64 _billboardChangeTimestamp = 0; quint64 _identityChangeTimestamp = 0; + float _fullRateDistance = FLT_MAX; float _maxAvatarDistance = FLT_MAX; + int _numAvatarsSentLastFrame = 0; int _numFramesSinceAdjustment = 0; + SimpleMovingAverage _avgOtherAvatarDataRate; }; From b0c7af1714d81f4ff7370a474a350521ea2a534a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 6 May 2015 10:41:36 -0700 Subject: [PATCH 05/39] store last seq for node/packet type combo --- libraries/networking/src/LimitedNodeList.h | 3 --- libraries/networking/src/Node.cpp | 10 ++++++++++ libraries/networking/src/Node.h | 9 ++++++++- libraries/networking/src/PacketHeaders.h | 3 +++ 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 53bf6ea2d8..7c710185b1 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -14,7 +14,6 @@ #include #include -#include #include #include @@ -79,8 +78,6 @@ namespace PingType { const PingType_t Symmetric = 3; } -typedef std::map PacketTypeSequenceMap; - class LimitedNodeList : public QObject, public Dependency { Q_OBJECT SINGLETON_DEPENDENCY diff --git a/libraries/networking/src/Node.cpp b/libraries/networking/src/Node.cpp index 4abae367d7..cf0902556a 100644 --- a/libraries/networking/src/Node.cpp +++ b/libraries/networking/src/Node.cpp @@ -129,6 +129,16 @@ void Node::activateSymmetricSocket() { _activeSocket = &_symmetricSocket; } +PacketSequenceNumber Node::getLastSequenceNumberForPacketType(PacketType packetType) const { + const PacketSequenceNumber MISSING_SEQUENCE_NUMBER = 0; + auto typeMatch = _lastSequenceNumbers.find(packetType); + if (typeMatch != _lastSequenceNumbers.end()) { + return typeMatch->second; + } else { + return MISSING_SEQUENCE_NUMBER; + } +} + QDataStream& operator<<(QDataStream& out, const Node& node) { out << node._type; out << node._uuid; diff --git a/libraries/networking/src/Node.h b/libraries/networking/src/Node.h index 420c52b423..0836a448b2 100644 --- a/libraries/networking/src/Node.h +++ b/libraries/networking/src/Node.h @@ -23,6 +23,7 @@ #include "HifiSockAddr.h" #include "NetworkPeer.h" #include "NodeData.h" +#include "PacketHeaders.h" #include "SimpleMovingAverage.h" #include "MovingPercentile.h" @@ -43,7 +44,7 @@ namespace NodeType { class Node : public NetworkPeer { Q_OBJECT -public: +public: Node(const QUuid& uuid, NodeType_t type, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket, bool canAdjustLocks, bool canRez); ~Node(); @@ -86,6 +87,10 @@ public: void activatePublicSocket(); void activateLocalSocket(); void activateSymmetricSocket(); + + void setLastSequenceNumberForPacketType(PacketSequenceNumber sequenceNumber, PacketType packetType) + { _lastSequenceNumbers[packetType] = sequenceNumber; } + PacketSequenceNumber getLastSequenceNumberForPacketType(PacketType packetType) const; friend QDataStream& operator<<(QDataStream& out, const Node& node); friend QDataStream& operator>>(QDataStream& in, Node& node); @@ -109,6 +114,8 @@ private: MovingPercentile _clockSkewMovingPercentile; bool _canAdjustLocks; bool _canRez; + + PacketTypeSequenceMap _lastSequenceNumbers; }; QDebug operator<<(QDebug debug, const Node &message); diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index 280b5587eb..96b7850b3f 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -15,6 +15,7 @@ #pragma once #include +#include #include #include @@ -84,6 +85,8 @@ enum PacketType { typedef char PacketVersion; typedef uint16_t PacketSequenceNumber; +typedef std::map PacketTypeSequenceMap; + const QSet NON_VERIFIED_PACKETS = QSet() << PacketTypeDomainServerRequireDTLS << PacketTypeDomainConnectRequest << PacketTypeDomainList << PacketTypeDomainListRequest << PacketTypeDomainConnectionDenied From e2986f57020faab69f6572ca6b9f9db1221698f4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 6 May 2015 11:34:58 -0700 Subject: [PATCH 06/39] add get seq num, cleanup PacketHeaders methods --- libraries/networking/src/PacketHeaders.cpp | 50 ++++++++++++++++------ libraries/networking/src/PacketHeaders.h | 19 +++++--- 2 files changed, 48 insertions(+), 21 deletions(-) diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index 6c4f2a1352..a4894e522e 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -227,33 +227,55 @@ QByteArray hashForPacketAndConnectionUUID(const QByteArray& packet, const QUuid& QCryptographicHash::Md5); } -void replaceHashInPacketGivenType(QByteArray& packet, PacketType packetType, const QUuid& connectionUUID) { +PacketSequenceNumber sequenceNumberFromHeader(const QByteArray& packet, PacketType packetType) { + if (packetType == PacketTypeUnknown) { + packetType = packetTypeForPacket(packet); + } + + if (SEQUENCE_NUMBERED_PACKETS.contains(packetType)) { + bool converted = false; + PacketSequenceNumber sequenceNumber = packet.mid(sequenceNumberOffsetForPacketType(packetType), + sizeof(PacketSequenceNumber)).toShort(&converted); + + if (converted) { + return sequenceNumber; + } + } + + return DEFAULT_SEQUENCE_NUMBER; +} + +void replaceHashInPacket(QByteArray& packet, const QUuid& connectionUUID, PacketType packetType) { + if (packetType == PacketTypeUnknown) { + packetType = packetTypeForPacket(packet); + } + packet.replace(hashOffsetForPacketType(packetType), NUM_BYTES_MD5_HASH, - hashForPacketAndConnectionUUID(packet, connectionUUID)); + hashForPacketAndConnectionUUID(packet, connectionUUID)); } -void replaceHashInPacket(QByteArray& packet, const QUuid& connectionUUID) { - replaceHashInPacketGivenType(packet, packetTypeForPacket(packet), connectionUUID); -} +void replaceSequenceNumberInPacket(QByteArray& packet, PacketSequenceNumber sequenceNumber, PacketType packetType) { + if (packetType == PacketTypeUnknown) { + packetType = packetTypeForPacket(packet); + } -void replaceSequenceNumberInPacketGivenType(QByteArray& packet, PacketType packetType, PacketSequenceNumber sequenceNumber) { packet.replace(sequenceNumberOffsetForPacketType(packetType), sizeof(PacketSequenceNumber), reinterpret_cast(&sequenceNumber)); -} - -void replaceSequenceNumberInPacket(QByteArray& packet, PacketSequenceNumber sequenceNumber) { - replaceSequenceNumberInPacketGivenType(packet, packetTypeForPacket(packet), sequenceNumber); } void replaceHashAndSequenceNumberInPacketGivenType(QByteArray& packet, PacketType packetType, const QUuid& connectionUUID, PacketSequenceNumber sequenceNumber) { - replaceHashInPacketGivenType(packet, packetType, connectionUUID); - replaceSequenceNumberInPacketGivenType(packet, packetType, sequenceNumber); + } +void replaceHashAndSequenceNumberInPacket(QByteArray& packet, const QUuid& connectionUUID, PacketSequenceNumber sequenceNumber, + PacketType packetType) { + if (packetType == PacketTypeUnknown) { + packetType = packetTypeForPacket(packet); + } -void replaceHashAndSequenceNumberInPacket(QByteArray& packet, const QUuid& connectionUUID, PacketSequenceNumber sequenceNumber) { - replaceHashAndSequenceNumberInPacketGivenType(packet, packetTypeForPacket(packet), connectionUUID, sequenceNumber); + replaceHashInPacket(packet, connectionUUID, packetType); + replaceSequenceNumberInPacket(packet, sequenceNumber, packetType); } PacketType packetTypeForPacket(const QByteArray& packet) { diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index 96b7850b3f..1cbf2df196 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -83,7 +83,9 @@ enum PacketType { }; typedef char PacketVersion; + typedef uint16_t PacketSequenceNumber; +const PacketSequenceNumber DEFAULT_SEQUENCE_NUMBER = 0; typedef std::map PacketTypeSequenceMap; @@ -130,15 +132,18 @@ int sequenceNumberOffsetForPacketType(PacketType packetType); QByteArray hashFromPacketHeader(const QByteArray& packet); QByteArray hashForPacketAndConnectionUUID(const QByteArray& packet, const QUuid& connectionUUID); -void replaceHashInPacketGivenType(QByteArray& packet, PacketType packetType, const QUuid& connectionUUID); -void replaceHashInPacket(QByteArray& packet, const QUuid& connectionUUID); +// NOTE: The following four methods accept a PacketType which defaults to PacketTypeUnknown. +// If the caller has already looked at the packet type and can provide it then the methods below won't have to look it up. -void replaceSequenceNumberInPacketGivenType(QByteArray& packet, PacketType packetType, PacketSequenceNumber sequenceNumber); -void replaceSequenceNumberInPacket(QByteArray& packet, PacketSequenceNumber sequenceNumber); +PacketSequenceNumber sequenceNumberFromHeader(const QByteArray& packet, PacketType packetType = PacketTypeUnknown); -void replaceHashAndSequenceNumberInPacketGivenType(QByteArray& packet, PacketType packetType, - const QUuid& connectionUUID, PacketSequenceNumber sequenceNumber); -void replaceHashAndSequenceNumberInPacket(QByteArray& packet, const QUuid& connectionUUID, PacketSequenceNumber sequenceNumber); +void replaceHashInPacket(QByteArray& packet, const QUuid& connectionUUID, PacketType packetType = PacketTypeUnknown); + +void replaceSequenceNumberInPacket(QByteArray& packet, PacketSequenceNumber sequenceNumber, + PacketType packetType = PacketTypeUnknown); + +void replaceHashAndSequenceNumberInPacket(QByteArray& packet, const QUuid& connectionUUID, PacketSequenceNumber sequenceNumber, + PacketType packetType = PacketTypeUnknown); int arithmeticCodingValueFromBuffer(const char* checkValue); int numBytesArithmeticCodingFromBuffer(const char* checkValue); From ba9ed12415e8a5c09225d4505f0339ef7baa9a52 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 6 May 2015 11:35:34 -0700 Subject: [PATCH 07/39] store last sequence number sent with data --- libraries/networking/src/LimitedNodeList.cpp | 7 +++++++ libraries/networking/src/Node.cpp | 3 +-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 61b98ffa44..91716dca2f 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -348,6 +348,13 @@ int LimitedNodeList::updateNodeWithDataFromPacket(const SharedNodePointer& match matchingNode->setLastHeardMicrostamp(usecTimestampNow()); + // if this was a sequence numbered packet we should store the last seq number for + // a packet of this type for this node + PacketType packetType = packetTypeForPacket(packet); + if (SEQUENCE_NUMBERED_PACKETS.contains(packetType)) { + matchingNode->setLastSequenceNumberForPacketType(sequenceNumberFromHeader(packet, packetType), packetType); + } + NodeData* linkedData = matchingNode->getLinkedData(); if (!linkedData && linkedDataCreateCallback) { linkedDataCreateCallback(matchingNode.data()); diff --git a/libraries/networking/src/Node.cpp b/libraries/networking/src/Node.cpp index cf0902556a..ddc0571db4 100644 --- a/libraries/networking/src/Node.cpp +++ b/libraries/networking/src/Node.cpp @@ -130,12 +130,11 @@ void Node::activateSymmetricSocket() { } PacketSequenceNumber Node::getLastSequenceNumberForPacketType(PacketType packetType) const { - const PacketSequenceNumber MISSING_SEQUENCE_NUMBER = 0; auto typeMatch = _lastSequenceNumbers.find(packetType); if (typeMatch != _lastSequenceNumbers.end()) { return typeMatch->second; } else { - return MISSING_SEQUENCE_NUMBER; + return DEFAULT_SEQUENCE_NUMBER; } } From 460abd85b9d3f59ffba7cb7b5177914aba5e1edb Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 6 May 2015 11:35:45 -0700 Subject: [PATCH 08/39] don't double send data to a receiver --- assignment-client/src/avatars/AvatarMixer.cpp | 20 ++++++++++++++++++- .../src/avatars/AvatarMixerClientData.cpp | 10 ++++++++++ .../src/avatars/AvatarMixerClientData.h | 9 ++++++--- 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 99ae98fb14..f401f62e99 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -160,7 +160,7 @@ void AvatarMixer::broadcastAvatarData() { // reset packet pointers for this node mixedAvatarByteArray.resize(numPacketHeaderBytes); - + AvatarData& avatar = nodeData->getAvatar(); glm::vec3 myPosition = avatar.getPosition(); @@ -256,8 +256,26 @@ void AvatarMixer::broadcastAvatarData() { && distribution(generator) > (nodeData->getFullRateDistance() / distanceToAvatar)) { return; } + + PacketSequenceNumber lastSeqToReceiver = nodeData->getLastBroadcastSequenceNumber(otherNode->getUUID()); + PacketSequenceNumber lastSeqFromSender = otherNode->getLastSequenceNumberForPacketType(PacketTypeAvatarData); + assert(lastSeqToReceiver <= lastSeqFromSender); + + // make sure we haven't already sent this data from this sender to this receiver + // or that somehow we haven't sent + if (lastSeqToReceiver == lastSeqFromSender) { + return; + } + + // we're going to send this avatar + + // increment the number of avatars sent to this reciever nodeData->incrementNumAvatarsSentLastFrame(); + + // set the last sent sequence number for this sender on the receiver + nodeData->setLastBroadcastSequenceNumber(otherNode->getUUID(), + otherNode->getLastSequenceNumberForPacketType(PacketTypeAvatarData)); QByteArray avatarByteArray; avatarByteArray.append(otherNode->getUUID().toRfc4122()); diff --git a/assignment-client/src/avatars/AvatarMixerClientData.cpp b/assignment-client/src/avatars/AvatarMixerClientData.cpp index 17330ac891..e3506a25e5 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.cpp +++ b/assignment-client/src/avatars/AvatarMixerClientData.cpp @@ -25,6 +25,16 @@ bool AvatarMixerClientData::checkAndSetHasReceivedFirstPackets() { return oldValue; } +PacketSequenceNumber AvatarMixerClientData::getLastBroadcastSequenceNumber(const QUuid& nodeUUID) const { + // return the matching PacketSequenceNumber, or the default if we don't have it + auto nodeMatch = _lastBroadcastSequenceNumbers.find(nodeUUID); + if (nodeMatch != _lastBroadcastSequenceNumbers.end()) { + return nodeMatch->second; + } else { + return DEFAULT_SEQUENCE_NUMBER; + } +} + void AvatarMixerClientData::loadJSONStats(QJsonObject& jsonObject) const { jsonObject["display_name"] = _avatar.getDisplayName(); jsonObject["full_rate_distance"] = _fullRateDistance; diff --git a/assignment-client/src/avatars/AvatarMixerClientData.h b/assignment-client/src/avatars/AvatarMixerClientData.h index d569a79e64..d1dc996e39 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.h +++ b/assignment-client/src/avatars/AvatarMixerClientData.h @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -23,6 +24,7 @@ #include #include #include +#include const QString OUTBOUND_AVATAR_DATA_STATS_KEY = "outbound_av_data_kbps"; @@ -34,8 +36,9 @@ public: bool checkAndSetHasReceivedFirstPackets(); - PacketSequenceNumber getLastBroadcastSequenceNumber() const { return _lastBroadcastSequenceNumber; } - void setLastBroadcastSequenceNumber(PacketSequenceNumber sequenceNumber) { _lastBroadcastSequenceNumber = sequenceNumber; } + PacketSequenceNumber getLastBroadcastSequenceNumber(const QUuid& nodeUUID) const; + void setLastBroadcastSequenceNumber(const QUuid& nodeUUID, PacketSequenceNumber sequenceNumber) + { _lastBroadcastSequenceNumbers[nodeUUID] = sequenceNumber; } quint64 getBillboardChangeTimestamp() const { return _billboardChangeTimestamp; } void setBillboardChangeTimestamp(quint64 billboardChangeTimestamp) { _billboardChangeTimestamp = billboardChangeTimestamp; } @@ -66,7 +69,7 @@ public: private: AvatarData _avatar; - PacketSequenceNumber _lastBroadcastSequenceNumber = 0; + std::unordered_map _lastBroadcastSequenceNumbers; bool _hasReceivedFirstPackets = false; quint64 _billboardChangeTimestamp = 0; From 0d1c1bf8dd286161c4a4568ff9878062ed0c040c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 6 May 2015 11:51:46 -0700 Subject: [PATCH 09/39] lock NodeData when attempting to read stats --- assignment-client/src/avatars/AvatarMixer.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index f401f62e99..f87c7e31a7 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -447,11 +447,14 @@ void AvatarMixer::sendStatsPacket() { AvatarMixerClientData* clientData = static_cast(node->getLinkedData()); if (clientData) { - clientData->loadJSONStats(avatarStats); + MutexTryLocker lock(clientData->getMutex()); + if (lock.isLocked()) { + clientData->loadJSONStats(avatarStats); - // add the diff between the full outbound bandwidth and the measured bandwidth for AvatarData send only - avatarStats["delta_full_vs_avatar_data_kbps"] = - avatarStats[NODE_OUTBOUND_KBPS_STAT_KEY].toDouble() - avatarStats[OUTBOUND_AVATAR_DATA_STATS_KEY].toDouble(); + // add the diff between the full outbound bandwidth and the measured bandwidth for AvatarData send only + avatarStats["delta_full_vs_avatar_data_kbps"] = + avatarStats[NODE_OUTBOUND_KBPS_STAT_KEY].toDouble() - avatarStats[OUTBOUND_AVATAR_DATA_STATS_KEY].toDouble(); + } } avatarsObject[uuidStringWithoutCurlyBraces(node->getUUID())] = avatarStats; From c5e189bbf2ece0d722d4945ec775cdbc1b1da3a9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 6 May 2015 11:52:03 -0700 Subject: [PATCH 10/39] use new PacketHeaders calls from LimitedNodeList --- libraries/networking/src/LimitedNodeList.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 91716dca2f..0c4943b6ae 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -270,11 +270,10 @@ qint64 LimitedNodeList::writeDatagram(const QByteArray& datagram, if (SEQUENCE_NUMBERED_PACKETS.contains(packetType)) { PacketSequenceNumber sequenceNumber = getNextSequenceNumberForPacket(destinationNode->getUUID(), packetType); qDebug() << "Sequence number for this packet is" << sequenceNumber; - replaceHashAndSequenceNumberInPacketGivenType(datagramCopy, packetType, - destinationNode->getConnectionSecret(), - sequenceNumber); + replaceHashAndSequenceNumberInPacket(datagramCopy, destinationNode->getConnectionSecret(), + sequenceNumber, packetType); } else { - replaceHashInPacketGivenType(datagramCopy, packetType, destinationNode->getConnectionSecret()); + replaceHashInPacket(datagramCopy, destinationNode->getConnectionSecret(), packetType); } emit dataSent(destinationNode->getType(), datagram.size()); From 1fdf2c78037292f4ad092dbe026248a2f2561ac0 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 6 May 2015 13:35:53 -0700 Subject: [PATCH 11/39] Don't flash whole screen when audio clips --- interface/src/ui/ApplicationOverlay.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index c044bb0674..351db9996c 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -887,12 +887,6 @@ void ApplicationOverlay::renderAudioMeter() { } bool isClipping = ((audio->getTimeSinceLastClip() > 0.0f) && (audio->getTimeSinceLastClip() < CLIPPING_INDICATOR_TIME)); - if ((audio->getTimeSinceLastClip() > 0.0f) && (audio->getTimeSinceLastClip() < CLIPPING_INDICATOR_TIME)) { - const float MAX_MAGNITUDE = 0.7f; - float magnitude = MAX_MAGNITUDE * (1 - audio->getTimeSinceLastClip() / CLIPPING_INDICATOR_TIME); - renderCollisionOverlay(glCanvas->width(), glCanvas->height(), magnitude, 1.0f); - } - DependencyManager::get()->render(MIRROR_VIEW_LEFT_PADDING + AUDIO_METER_GAP, audioMeterY, cameraSpace, boxed); DependencyManager::get()->render(glCanvas->width(), glCanvas->height()); From ff676958e8ab8af43aedea008949647c9d34c067 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 6 May 2015 14:24:11 -0700 Subject: [PATCH 12/39] fix hash replacement in PacketHeaders --- assignment-client/src/avatars/AvatarMixer.cpp | 5 +++++ libraries/networking/src/LimitedNodeList.cpp | 5 ++--- libraries/networking/src/PacketHeaders.cpp | 21 ++++++++----------- libraries/networking/src/PacketHeaders.h | 1 + 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index f87c7e31a7..3d0a71993a 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -259,12 +259,17 @@ void AvatarMixer::broadcastAvatarData() { PacketSequenceNumber lastSeqToReceiver = nodeData->getLastBroadcastSequenceNumber(otherNode->getUUID()); PacketSequenceNumber lastSeqFromSender = otherNode->getLastSequenceNumberForPacketType(PacketTypeAvatarData); + + qDebug() << "Last sent to receiver" << node->getUUID() << "was" << lastSeqToReceiver; + qDebug() << "Last sent from sender" << otherNode->getUUID() << "was" << lastSeqFromSender; assert(lastSeqToReceiver <= lastSeqFromSender); // make sure we haven't already sent this data from this sender to this receiver // or that somehow we haven't sent if (lastSeqToReceiver == lastSeqFromSender) { + qDebug() << "Not sending a data for" << otherNode->getUUID() << "to" << node->getUUID() + << "since it has already been sent."; return; } diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 0c4943b6ae..5d04122d19 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -267,15 +267,14 @@ qint64 LimitedNodeList::writeDatagram(const QByteArray& datagram, PacketType packetType = packetTypeForPacket(datagramCopy); // perform replacement of hash and optionally also sequence number in the header - if (SEQUENCE_NUMBERED_PACKETS.contains(packetType)) { + if (SEQUENCE_NUMBERED_PACKETS.contains(packetType)) { PacketSequenceNumber sequenceNumber = getNextSequenceNumberForPacket(destinationNode->getUUID(), packetType); - qDebug() << "Sequence number for this packet is" << sequenceNumber; replaceHashAndSequenceNumberInPacket(datagramCopy, destinationNode->getConnectionSecret(), sequenceNumber, packetType); } else { replaceHashInPacket(datagramCopy, destinationNode->getConnectionSecret(), packetType); } - + emit dataSent(destinationNode->getType(), datagram.size()); auto bytesWritten = writeDatagram(datagramCopy, *destinationSockAddr, destinationNode->getConnectionSecret()); // Keep track of per-destination-node bandwidth diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index a4894e522e..a214c9c9c4 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -55,7 +55,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketTypeInjectAudio: return 1; case PacketTypeAvatarData: - return 5; + return 6; case PacketTypeAvatarIdentity: return 1; case PacketTypeEnvironmentData: @@ -188,8 +188,12 @@ int numBytesForPacketHeader(const char* packet) { return numBytesForPacketHeaderGivenPacketType(packetType); } +int numBytesForArithmeticCodedPacketType(PacketType packetType) { + return (int) ceilf((float) packetType / 255); +} + int numBytesForPacketHeaderGivenPacketType(PacketType packetType) { - return (int) ceilf((float) packetType / 255) + return numBytesForArithmeticCodedPacketType(packetType) + numHashBytesForType(packetType) + numSequenceNumberBytesForType(packetType) + NUM_STATIC_HEADER_BYTES; @@ -209,9 +213,7 @@ QUuid uuidFromPacketHeader(const QByteArray& packet) { } int hashOffsetForPacketType(PacketType packetType) { - return numBytesForPacketHeaderGivenPacketType(packetType) - - (SEQUENCE_NUMBERED_PACKETS.contains(packetType) ? sizeof(PacketSequenceNumber) : 0) - - NUM_BYTES_RFC4122_UUID; + return numBytesForArithmeticCodedPacketType(packetType) + NUM_STATIC_HEADER_BYTES; } int sequenceNumberOffsetForPacketType(PacketType packetType) { @@ -249,7 +251,7 @@ void replaceHashInPacket(QByteArray& packet, const QUuid& connectionUUID, Packet if (packetType == PacketTypeUnknown) { packetType = packetTypeForPacket(packet); } - + packet.replace(hashOffsetForPacketType(packetType), NUM_BYTES_MD5_HASH, hashForPacketAndConnectionUUID(packet, connectionUUID)); } @@ -260,14 +262,9 @@ void replaceSequenceNumberInPacket(QByteArray& packet, PacketSequenceNumber sequ } packet.replace(sequenceNumberOffsetForPacketType(packetType), - sizeof(PacketSequenceNumber), reinterpret_cast(&sequenceNumber)); + sizeof(PacketSequenceNumber), reinterpret_cast(&sequenceNumber), sizeof(PacketSequenceNumber)); } -void replaceHashAndSequenceNumberInPacketGivenType(QByteArray& packet, PacketType packetType, - const QUuid& connectionUUID, PacketSequenceNumber sequenceNumber) { - -} - void replaceHashAndSequenceNumberInPacket(QByteArray& packet, const QUuid& connectionUUID, PacketSequenceNumber sequenceNumber, PacketType packetType) { if (packetType == PacketTypeUnknown) { diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index 1cbf2df196..e057628924 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -122,6 +122,7 @@ int numSequenceNumberBytesForType(PacketType packetType); int numBytesForPacketHeader(const QByteArray& packet); int numBytesForPacketHeader(const char* packet); +int numBytesForArithmeticCodedPacketType(PacketType packetType); int numBytesForPacketHeaderGivenPacketType(PacketType packetType); QUuid uuidFromPacketHeader(const QByteArray& packet); From e540a6dbb34df936b5e04d47db15761ff73b3169 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 6 May 2015 14:48:10 -0700 Subject: [PATCH 13/39] fix packet sequence number unmarshal --- assignment-client/src/avatars/AvatarMixer.cpp | 5 +---- libraries/networking/src/PacketHeaders.cpp | 12 ++++-------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 3d0a71993a..e77c518ead 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -260,14 +260,11 @@ void AvatarMixer::broadcastAvatarData() { PacketSequenceNumber lastSeqToReceiver = nodeData->getLastBroadcastSequenceNumber(otherNode->getUUID()); PacketSequenceNumber lastSeqFromSender = otherNode->getLastSequenceNumberForPacketType(PacketTypeAvatarData); - qDebug() << "Last sent to receiver" << node->getUUID() << "was" << lastSeqToReceiver; - qDebug() << "Last sent from sender" << otherNode->getUUID() << "was" << lastSeqFromSender; - assert(lastSeqToReceiver <= lastSeqFromSender); // make sure we haven't already sent this data from this sender to this receiver // or that somehow we haven't sent - if (lastSeqToReceiver == lastSeqFromSender) { + if (lastSeqToReceiver == lastSeqFromSender && lastSeqToReceiver != 0) { qDebug() << "Not sending a data for" << otherNode->getUUID() << "to" << node->getUUID() << "since it has already been sent."; return; diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index a214c9c9c4..74484307d2 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -233,18 +233,14 @@ PacketSequenceNumber sequenceNumberFromHeader(const QByteArray& packet, PacketTy if (packetType == PacketTypeUnknown) { packetType = packetTypeForPacket(packet); } + + PacketSequenceNumber result = DEFAULT_SEQUENCE_NUMBER; if (SEQUENCE_NUMBERED_PACKETS.contains(packetType)) { - bool converted = false; - PacketSequenceNumber sequenceNumber = packet.mid(sequenceNumberOffsetForPacketType(packetType), - sizeof(PacketSequenceNumber)).toShort(&converted); - - if (converted) { - return sequenceNumber; - } + memcpy(&result, packet.data() + sequenceNumberOffsetForPacketType(packetType), sizeof(PacketSequenceNumber)); } - return DEFAULT_SEQUENCE_NUMBER; + return result; } void replaceHashInPacket(QByteArray& packet, const QUuid& connectionUUID, PacketType packetType) { From b3f7ec15451f08b2c1cb5553210611348e909ed5 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 6 May 2015 16:49:51 -0700 Subject: [PATCH 14/39] keep track of starves and skips on other avatars --- assignment-client/src/avatars/AvatarMixer.cpp | 18 +++++++++++++++--- .../src/avatars/AvatarMixerClientData.cpp | 2 ++ .../src/avatars/AvatarMixerClientData.h | 9 +++++++++ 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index e77c518ead..f18d19814a 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -178,7 +178,13 @@ void AvatarMixer::broadcastAvatarData() { // keep track of outbound data rate specifically for avatar data int numAvatarDataBytes = 0; - + + // keep track of the number of other avatars held back in this frame + int numAvatarsHeldBack = 0; + + // keep track of the number of other avatar frames skipped + int numAvatarsWithSkippedFrames = 0; + // use the data rate specifically for avatar data for FRD adjustment checks float avatarDataRateLastSecond = nodeData->getOutboundAvatarDataKbps(); @@ -265,9 +271,11 @@ void AvatarMixer::broadcastAvatarData() { // make sure we haven't already sent this data from this sender to this receiver // or that somehow we haven't sent if (lastSeqToReceiver == lastSeqFromSender && lastSeqToReceiver != 0) { - qDebug() << "Not sending a data for" << otherNode->getUUID() << "to" << node->getUUID() - << "since it has already been sent."; + ++numAvatarsHeldBack; return; + } else if (lastSeqFromSender - lastSeqToReceiver > 1) { + // this is a skip - we still send the packet but capture the presence of the skip so we see it happening + ++numAvatarsWithSkippedFrames; } // we're going to send this avatar @@ -337,6 +345,10 @@ void AvatarMixer::broadcastAvatarData() { // record the bytes sent for other avatar data in the AvatarMixerClientData nodeData->recordSentAvatarData(numAvatarDataBytes + mixedAvatarByteArray.size()); + + // record the number of avatars held back this frame + nodeData->recordNumOtherAvatarStarves(numAvatarsHeldBack); + nodeData->recordNumOtherAvatarSkips(numAvatarsWithSkippedFrames); if (numOtherAvatars == 0) { // update the full rate distance to FLOAT_MAX since we didn't have any other avatars to send diff --git a/assignment-client/src/avatars/AvatarMixerClientData.cpp b/assignment-client/src/avatars/AvatarMixerClientData.cpp index e3506a25e5..dbdc573b96 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.cpp +++ b/assignment-client/src/avatars/AvatarMixerClientData.cpp @@ -40,6 +40,8 @@ void AvatarMixerClientData::loadJSONStats(QJsonObject& jsonObject) const { jsonObject["full_rate_distance"] = _fullRateDistance; jsonObject["max_avatar_distance"] = _maxAvatarDistance; jsonObject["num_avatars_sent_last_frame"] = _numAvatarsSentLastFrame; + jsonObject["avg_other_avatar_starves_per_second"] = getAvgNumOtherAvatarStarvesPerSecond(); + jsonObject["avg_other_avatar_skips_per_second"] = getAvgNumOtherAvatarSkipsPerSecond(); jsonObject[OUTBOUND_AVATAR_DATA_STATS_KEY] = getOutboundAvatarDataKbps(); } diff --git a/assignment-client/src/avatars/AvatarMixerClientData.h b/assignment-client/src/avatars/AvatarMixerClientData.h index d1dc996e39..d91dccbdaa 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.h +++ b/assignment-client/src/avatars/AvatarMixerClientData.h @@ -56,6 +56,12 @@ public: void incrementNumAvatarsSentLastFrame() { ++_numAvatarsSentLastFrame; } int getNumAvatarsSentLastFrame() const { return _numAvatarsSentLastFrame; } + void recordNumOtherAvatarStarves(int numAvatarsHeldBack) { _otherAvatarStarves.updateAverage((float) numAvatarsHeldBack); } + float getAvgNumOtherAvatarStarvesPerSecond() const { return _otherAvatarStarves.getAverageSampleValuePerSecond(); } + + void recordNumOtherAvatarSkips(int numOtherAvatarSkips) { _otherAvatarSkips.updateAverage((float) numOtherAvatarSkips); } + float getAvgNumOtherAvatarSkipsPerSecond() const { return _otherAvatarSkips.getAverageSampleValuePerSecond(); } + int getNumFramesSinceFRDAdjustment() const { return _numFramesSinceAdjustment; } void incrementNumFramesSinceFRDAdjustment() { ++_numFramesSinceAdjustment; } void resetNumFramesSinceFRDAdjustment() { _numFramesSinceAdjustment = 0; } @@ -81,6 +87,9 @@ private: int _numAvatarsSentLastFrame = 0; int _numFramesSinceAdjustment = 0; + SimpleMovingAverage _otherAvatarStarves; + SimpleMovingAverage _otherAvatarSkips; + SimpleMovingAverage _avgOtherAvatarDataRate; }; From e3acf861ff36e1de82412f177228b98818b1208d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 7 May 2015 14:07:14 -0700 Subject: [PATCH 15/39] fix for unverified datagram writes --- domain-server/src/DomainServer.cpp | 6 +-- libraries/networking/src/LimitedNodeList.cpp | 42 +++++++++++++++----- libraries/networking/src/LimitedNodeList.h | 5 +-- libraries/networking/src/NodeList.cpp | 7 ++-- 4 files changed, 41 insertions(+), 19 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index ea69b5bc95..7841381422 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -985,7 +985,7 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif // we need to break here and start a new packet // so send the current one - limitedNodeList->writeDatagram(broadcastPacket, node, senderSockAddr); + limitedNodeList->writeUnverifiedDatagram(broadcastPacket, node, senderSockAddr); // reset the broadcastPacket structure broadcastPacket.resize(numBroadcastPacketLeadBytes); @@ -998,9 +998,9 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif }); } } - + // always write the last broadcastPacket - limitedNodeList->writeDatagram(broadcastPacket, node, senderSockAddr); + limitedNodeList->writeUnverifiedDatagram(broadcastPacket, node, senderSockAddr); } void DomainServer::readAvailableDatagrams() { diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 5d04122d19..d8d1e9289b 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -230,8 +230,7 @@ qint64 LimitedNodeList::readDatagram(QByteArray& incomingPacket, QHostAddress* a return result; } -qint64 LimitedNodeList::writeDatagram(const QByteArray& datagram, const HifiSockAddr& destinationSockAddr, - const QUuid& connectionSecret) { +qint64 LimitedNodeList::writeDatagram(const QByteArray& datagram, const HifiSockAddr& destinationSockAddr) { // XXX can BandwidthRecorder be used for this? // stat collection for packets ++_numCollectedPackets; @@ -251,6 +250,12 @@ qint64 LimitedNodeList::writeDatagram(const QByteArray& datagram, const SharedNodePointer& destinationNode, const HifiSockAddr& overridenSockAddr) { if (destinationNode) { + PacketType packetType = packetTypeForPacket(datagram); + + if (NON_VERIFIED_PACKETS.contains(packetType)) { + return writeUnverifiedDatagram(datagram, destinationNode, overridenSockAddr); + } + // if we don't have an overridden address, assume they want to send to the node's active socket const HifiSockAddr* destinationSockAddr = &overridenSockAddr; if (overridenSockAddr.isNull()) { @@ -264,8 +269,14 @@ qint64 LimitedNodeList::writeDatagram(const QByteArray& datagram, } QByteArray datagramCopy = datagram; - PacketType packetType = packetTypeForPacket(datagramCopy); + // if we're here and the connection secret is null, debug out - this could be a problem + if (destinationNode->getConnectionSecret().isNull()) { + qDebug() << "LimitedNodeList::writeDatagram called for verified datagram with null connection secret for" + << "destination node" << destinationNode->getUUID() << " - this is either not secure or will cause" + << "this packet to be unverifiable on the receiving side."; + } + // perform replacement of hash and optionally also sequence number in the header if (SEQUENCE_NUMBERED_PACKETS.contains(packetType)) { PacketSequenceNumber sequenceNumber = getNextSequenceNumberForPacket(destinationNode->getUUID(), packetType); @@ -276,7 +287,7 @@ qint64 LimitedNodeList::writeDatagram(const QByteArray& datagram, } emit dataSent(destinationNode->getType(), datagram.size()); - auto bytesWritten = writeDatagram(datagramCopy, *destinationSockAddr, destinationNode->getConnectionSecret()); + auto bytesWritten = writeDatagram(datagramCopy, *destinationSockAddr); // Keep track of per-destination-node bandwidth destinationNode->recordBytesSent(bytesWritten); return bytesWritten; @@ -301,8 +312,21 @@ qint64 LimitedNodeList::writeUnverifiedDatagram(const QByteArray& datagram, cons } } - // don't use the node secret! - return writeDatagram(datagram, *destinationSockAddr, QUuid()); + PacketType packetType = packetTypeForPacket(datagram); + + // optionally peform sequence number replacement in the header + if (SEQUENCE_NUMBERED_PACKETS.contains(packetType)) { + + QByteArray datagramCopy = datagram; + + PacketSequenceNumber sequenceNumber = getNextSequenceNumberForPacket(destinationNode->getUUID(), packetType); + replaceSequenceNumberInPacket(datagramCopy, sequenceNumber, packetType); + + // send the datagram with sequence number replaced in header + return writeDatagram(datagramCopy, *destinationSockAddr); + } else { + return writeDatagram(datagram, *destinationSockAddr); + } } // didn't have a destinationNode to send to, return 0 @@ -310,7 +334,7 @@ qint64 LimitedNodeList::writeUnverifiedDatagram(const QByteArray& datagram, cons } qint64 LimitedNodeList::writeUnverifiedDatagram(const QByteArray& datagram, const HifiSockAddr& destinationSockAddr) { - return writeDatagram(datagram, destinationSockAddr, QUuid()); + return writeDatagram(datagram, destinationSockAddr); } qint64 LimitedNodeList::writeDatagram(const char* data, qint64 size, const SharedNodePointer& destinationNode, @@ -548,11 +572,11 @@ void LimitedNodeList::removeSilentNodes() { eachNodeHashIterator([&](NodeHash::iterator& it){ SharedNodePointer node = it->second; node->getMutex().lock(); - + if ((usecTimestampNow() - node->getLastHeardMicrostamp()) > (NODE_SILENCE_THRESHOLD_MSECS * USECS_PER_MSEC)) { // call the NodeHash erase to get rid of this node it = _nodeHash.unsafe_erase(it); - + killedNodes.insert(node); } else { // we didn't erase this node, push the iterator forwards diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 7c710185b1..9f8bf690bf 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -114,6 +114,7 @@ public: const HifiSockAddr& overridenSockAddr = HifiSockAddr()); qint64 writeUnverifiedDatagram(const QByteArray& datagram, const HifiSockAddr& destinationSockAddr); + qint64 writeDatagram(const char* data, qint64 size, const SharedNodePointer& destinationNode, const HifiSockAddr& overridenSockAddr = HifiSockAddr()); @@ -233,9 +234,7 @@ protected: LimitedNodeList(LimitedNodeList const&); // Don't implement, needed to avoid copies of singleton void operator=(LimitedNodeList const&); // Don't implement, needed to avoid copies of singleton - qint64 writeDatagram(const QByteArray& datagram, - const HifiSockAddr& destinationSockAddr, - const QUuid& connectionSecret); + qint64 writeDatagram(const QByteArray& datagram, const HifiSockAddr& destinationSockAddr); PacketSequenceNumber getNextSequenceNumberForPacket(const QUuid& nodeUUID, PacketType packetType); diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 179f054e42..7a60c51986 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -369,7 +369,7 @@ void NodeList::sendDomainServerCheckIn() { } if (!isUsingDTLS) { - writeDatagram(domainServerPacket, _domainHandler.getSockAddr(), QUuid()); + writeUnverifiedDatagram(domainServerPacket, _domainHandler.getSockAddr()); } const int NUM_DOMAIN_SERVER_CHECKINS_PER_STUN_REQUEST = 5; @@ -424,10 +424,9 @@ int NodeList::processDomainServerList(const QByteArray& packet) { _domainHandler.setUUID(uuidFromPacketHeader(packet)); _domainHandler.setIsConnected(true); } - + int readNodes = 0; - - + QDataStream packetStream(packet); packetStream.skipRawData(numBytesForPacketHeader(packet)); From fe011e6752771e1587103e09ae4011b3c008eb81 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 7 May 2015 14:13:27 -0700 Subject: [PATCH 16/39] keep track of out of order sends in AM --- assignment-client/src/avatars/AvatarMixer.cpp | 8 ++++++++ assignment-client/src/avatars/AvatarMixerClientData.cpp | 1 + assignment-client/src/avatars/AvatarMixerClientData.h | 3 +++ 3 files changed, 12 insertions(+) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index f18d19814a..ed663cd01a 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -268,6 +268,14 @@ void AvatarMixer::broadcastAvatarData() { assert(lastSeqToReceiver <= lastSeqFromSender); + if (lastSeqToReceiver > lastSeqFromSender) { + // Did we somehow get out of order packets from the sender? + // We don't expect this to happen - in RELEASE we add this to a trackable stat + // and in DEBUG we crash on the assert above + + } + + // make sure we haven't already sent this data from this sender to this receiver // or that somehow we haven't sent if (lastSeqToReceiver == lastSeqFromSender && lastSeqToReceiver != 0) { diff --git a/assignment-client/src/avatars/AvatarMixerClientData.cpp b/assignment-client/src/avatars/AvatarMixerClientData.cpp index dbdc573b96..197e9baf5e 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.cpp +++ b/assignment-client/src/avatars/AvatarMixerClientData.cpp @@ -42,6 +42,7 @@ void AvatarMixerClientData::loadJSONStats(QJsonObject& jsonObject) const { jsonObject["num_avatars_sent_last_frame"] = _numAvatarsSentLastFrame; jsonObject["avg_other_avatar_starves_per_second"] = getAvgNumOtherAvatarStarvesPerSecond(); jsonObject["avg_other_avatar_skips_per_second"] = getAvgNumOtherAvatarSkipsPerSecond(); + jsonObject["total_num_out_of_order_sends"] = _numOutOfOrderSends; jsonObject[OUTBOUND_AVATAR_DATA_STATS_KEY] = getOutboundAvatarDataKbps(); } diff --git a/assignment-client/src/avatars/AvatarMixerClientData.h b/assignment-client/src/avatars/AvatarMixerClientData.h index d91dccbdaa..7c7b1f585e 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.h +++ b/assignment-client/src/avatars/AvatarMixerClientData.h @@ -62,6 +62,8 @@ public: void recordNumOtherAvatarSkips(int numOtherAvatarSkips) { _otherAvatarSkips.updateAverage((float) numOtherAvatarSkips); } float getAvgNumOtherAvatarSkipsPerSecond() const { return _otherAvatarSkips.getAverageSampleValuePerSecond(); } + void incrementNumOutOfOrderSends() { ++_numOutOfOrderSends; } + int getNumFramesSinceFRDAdjustment() const { return _numFramesSinceAdjustment; } void incrementNumFramesSinceFRDAdjustment() { ++_numFramesSinceAdjustment; } void resetNumFramesSinceFRDAdjustment() { _numFramesSinceAdjustment = 0; } @@ -89,6 +91,7 @@ private: SimpleMovingAverage _otherAvatarStarves; SimpleMovingAverage _otherAvatarSkips; + int _numOutOfOrderSends = 0; SimpleMovingAverage _avgOtherAvatarDataRate; }; From 790f7a08cf2765ef4d5c1e54973e2b805e6b4a30 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 7 May 2015 14:34:06 -0700 Subject: [PATCH 17/39] clean up sequence numbers for killed sending nodes --- assignment-client/src/avatars/AvatarMixer.cpp | 26 +++++++++++++++++-- .../src/avatars/AvatarMixerClientData.h | 1 + 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index ed663cd01a..79b60ed3c4 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -272,9 +272,8 @@ void AvatarMixer::broadcastAvatarData() { // Did we somehow get out of order packets from the sender? // We don't expect this to happen - in RELEASE we add this to a trackable stat // and in DEBUG we crash on the assert above - + otherNodeData->incrementNumOutOfOrderSends(); } - // make sure we haven't already sent this data from this sender to this receiver // or that somehow we haven't sent @@ -374,12 +373,35 @@ void AvatarMixer::nodeKilled(SharedNodePointer killedNode) { if (killedNode->getType() == NodeType::Agent && killedNode->getLinkedData()) { auto nodeList = DependencyManager::get(); + // this was an avatar we were sending to other people // send a kill packet for it to our other nodes QByteArray killPacket = nodeList->byteArrayWithPopulatedHeader(PacketTypeKillAvatar); killPacket += killedNode->getUUID().toRfc4122(); nodeList->broadcastToNodes(killPacket, NodeSet() << NodeType::Agent); + + // we also want to remove sequence number data for this avatar on our other avatars + // so invoke the appropriate method on the AvatarMixerClientData for other avatars + nodeList->eachMatchingNode( + [&](const SharedNodePointer& node)->bool { + if (!node->getLinkedData()) { + return false; + } + + if (node->getUUID() == killedNode->getUUID()) { + return false; + } + + return true; + }, + [&](const SharedNodePointer& node) { + QMetaObject::invokeMethod(node->getLinkedData(), + "removeLastBroadcastSequenceNumber", + Qt::AutoConnection, + Q_ARG(const QUuid&, QUuid(killedNode->getUUID()))); + } + ); } } diff --git a/assignment-client/src/avatars/AvatarMixerClientData.h b/assignment-client/src/avatars/AvatarMixerClientData.h index 7c7b1f585e..3e10b8473a 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.h +++ b/assignment-client/src/avatars/AvatarMixerClientData.h @@ -39,6 +39,7 @@ public: PacketSequenceNumber getLastBroadcastSequenceNumber(const QUuid& nodeUUID) const; void setLastBroadcastSequenceNumber(const QUuid& nodeUUID, PacketSequenceNumber sequenceNumber) { _lastBroadcastSequenceNumbers[nodeUUID] = sequenceNumber; } + Q_INVOKABLE void removeLastBroadcastSequenceNumber(const QUuid& nodeUUID) { _lastBroadcastSequenceNumbers.erase(nodeUUID); } quint64 getBillboardChangeTimestamp() const { return _billboardChangeTimestamp; } void setBillboardChangeTimestamp(quint64 billboardChangeTimestamp) { _billboardChangeTimestamp = billboardChangeTimestamp; } From bfccf02912fece35f185aa59af894d46b9e07dda Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 7 May 2015 15:37:02 -0700 Subject: [PATCH 18/39] use lamdbas for linkedDataCreateCallback --- assignment-client/src/audio/AudioMixer.cpp | 10 +++------- assignment-client/src/avatars/AvatarMixer.cpp | 12 +++--------- assignment-client/src/octree/OctreeServer.cpp | 14 +++++--------- assignment-client/src/octree/OctreeServer.h | 2 -- libraries/networking/src/LimitedNodeList.h | 2 +- 5 files changed, 12 insertions(+), 28 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index a9c0e5ddf2..098569b4f8 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -65,12 +65,6 @@ const QString AUDIO_MIXER_LOGGING_TARGET_NAME = "audio-mixer"; const QString AUDIO_ENV_GROUP_KEY = "audio_env"; const QString AUDIO_BUFFER_GROUP_KEY = "audio_buffer"; -void attachNewNodeDataToNode(Node *newNode) { - if (!newNode->getLinkedData()) { - newNode->setLinkedData(new AudioMixerClientData()); - } -} - InboundAudioStream::Settings AudioMixer::_streamSettings; bool AudioMixer::_printStreamStats = false; @@ -687,7 +681,9 @@ void AudioMixer::run() { nodeList->addNodeTypeToInterestSet(NodeType::Agent); - nodeList->linkedDataCreateCallback = attachNewNodeDataToNode; + nodeList->linkedDataCreateCallback = [](Node* node) { + node->setLinkedData(new AudioMixerClientData()); + }; // wait until we have the domain-server settings, otherwise we bail DomainHandler& domainHandler = nodeList->getDomainHandler(); diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 79b60ed3c4..ade1c5a444 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -56,14 +56,6 @@ AvatarMixer::~AvatarMixer() { _broadcastThread.wait(); } -void attachAvatarDataToNode(Node* newNode) { - if (!newNode->getLinkedData()) { - // setup the client linked data - default the number of frames since adjustment - // to our number of frames per second - newNode->setLinkedData(new AvatarMixerClientData()); - } -} - const float BILLBOARD_AND_IDENTITY_SEND_PROBABILITY = 1.0f / 300.0f; // NOTE: some additional optimizations to consider. @@ -519,7 +511,9 @@ void AvatarMixer::run() { auto nodeList = DependencyManager::get(); nodeList->addNodeTypeToInterestSet(NodeType::Agent); - nodeList->linkedDataCreateCallback = attachAvatarDataToNode; + nodeList->linkedDataCreateCallback = [] (Node* node) { + node->setLinkedData(new AvatarMixerClientData()); + }; // setup the timer that will be fired on the broadcast thread _broadcastTimer = new QTimer(); diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 9abace0c5b..361a619744 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -213,14 +213,6 @@ void OctreeServer::trackProcessWaitTime(float time) { _averageProcessWaitTime.updateAverage(time); } -void OctreeServer::attachQueryNodeToNode(Node* newNode) { - if (!newNode->getLinkedData() && _instance) { - OctreeQueryNode* newQueryNodeData = _instance->createOctreeQueryNode(); - newQueryNodeData->init(); - newNode->setLinkedData(newQueryNodeData); - } -} - OctreeServer::OctreeServer(const QByteArray& packet) : ThreadedAssignment(packet), _argc(0), @@ -1132,7 +1124,11 @@ void OctreeServer::run() { setvbuf(stdout, NULL, _IOLBF, 0); #endif - nodeList->linkedDataCreateCallback = &OctreeServer::attachQueryNodeToNode; + nodeList->linkedDataCreateCallback = [] (Node* node) { + OctreeQueryNode* newQueryNodeData = _instance->createOctreeQueryNode(); + newQueryNodeData->init(); + node->setLinkedData(newQueryNodeData); + }; srand((unsigned)time(0)); diff --git a/assignment-client/src/octree/OctreeServer.h b/assignment-client/src/octree/OctreeServer.h index 41cd3259cf..ab75efe346 100644 --- a/assignment-client/src/octree/OctreeServer.h +++ b/assignment-client/src/octree/OctreeServer.h @@ -75,8 +75,6 @@ public: virtual bool hasSpecialPacketToSend(const SharedNodePointer& node) { return false; } virtual int sendSpecialPacket(const SharedNodePointer& node, OctreeQueryNode* queryNode, int& packetsSent) { return 0; } - static void attachQueryNodeToNode(Node* newNode); - static float SKIP_TIME; // use this for trackXXXTime() calls for non-times static void trackLoopTime(float time) { _averageLoopTime.updateAverage(time); } diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 9f8bf690bf..9420b698ec 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -121,7 +121,7 @@ public: qint64 writeUnverifiedDatagram(const char* data, qint64 size, const SharedNodePointer& destinationNode, const HifiSockAddr& overridenSockAddr = HifiSockAddr()); - void(*linkedDataCreateCallback)(Node *); + void (*linkedDataCreateCallback)(Node *); int size() const { return _nodeHash.size(); } From 52397bf87af1ca5d2431f108cf55dfadb207a5fe Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 8 May 2015 15:59:39 +0200 Subject: [PATCH 19/39] Fix wireframe render for meshes with special properties --- libraries/render-utils/src/Model.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index eb010f874d..db95005a09 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -2068,6 +2068,12 @@ void Model::segregateMeshGroups() { bool hasSpecular = mesh.hasSpecularTexture(); bool hasLightmap = mesh.hasEmissiveTexture(); bool isSkinned = state.clusterMatrices.size() > 1; + bool isWireframe = this->isWireframe(); + + if (isWireframe) { + translucentMesh = hasTangents = hasSpecular = hasLightmap = isSkinned = false; + } + QString materialID; // create a material name from all the parts. If there's one part, this will be a single material and its @@ -2085,7 +2091,7 @@ void Model::segregateMeshGroups() { qCDebug(renderutils) << "materialID:" << materialID << "parts:" << mesh.parts.size(); } - RenderKey key(translucentMesh, hasLightmap, hasTangents, hasSpecular, isSkinned, isWireframe()); + RenderKey key(translucentMesh, hasLightmap, hasTangents, hasSpecular, isSkinned, isWireframe); // reuse or create the bucket corresponding to that key and insert the mesh as unsorted _renderBuckets[key.getRaw()]._unsortedMeshes.insertMulti(materialID, i); From 805250d1e1ec21ec84d51be0271447f857f9559b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 8 May 2015 09:25:44 -0700 Subject: [PATCH 20/39] don't double conditional to fire SN assert --- assignment-client/src/avatars/AvatarMixer.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index ade1c5a444..0b510be151 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -258,13 +258,14 @@ void AvatarMixer::broadcastAvatarData() { PacketSequenceNumber lastSeqToReceiver = nodeData->getLastBroadcastSequenceNumber(otherNode->getUUID()); PacketSequenceNumber lastSeqFromSender = otherNode->getLastSequenceNumberForPacketType(PacketTypeAvatarData); - assert(lastSeqToReceiver <= lastSeqFromSender); - if (lastSeqToReceiver > lastSeqFromSender) { // Did we somehow get out of order packets from the sender? // We don't expect this to happen - in RELEASE we add this to a trackable stat - // and in DEBUG we crash on the assert above + // and in DEBUG we crash on the assert + otherNodeData->incrementNumOutOfOrderSends(); + + assert(false); } // make sure we haven't already sent this data from this sender to this receiver From 0b6a815a20f824c5b8c6c82490fe541f97825067 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 8 May 2015 20:17:01 -0700 Subject: [PATCH 21/39] moved zone stage properties into a group --- examples/html/entityProperties.html | 24 +-- .../src/EntityTreeRenderer.cpp | 10 +- .../entities/src/EntityItemProperties.cpp | 59 ++---- libraries/entities/src/EntityItemProperties.h | 11 +- .../entities/src/EntityItemPropertiesMacros.h | 14 ++ libraries/entities/src/StagePropertyGroup.cpp | 198 ++++++++++++++++++ libraries/entities/src/StagePropertyGroup.h | 87 ++++++++ libraries/entities/src/ZoneEntityItem.cpp | 71 ++----- libraries/entities/src/ZoneEntityItem.h | 33 +-- 9 files changed, 358 insertions(+), 149 deletions(-) create mode 100644 libraries/entities/src/StagePropertyGroup.cpp create mode 100644 libraries/entities/src/StagePropertyGroup.h diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index 26bcc63f15..bdbfbdf6b6 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -467,7 +467,7 @@ elZoneSections[i].style.display = 'block'; } - elZoneStageSunModelEnabled.checked = properties.stageSunModelEnabled; + elZoneStageSunModelEnabled.checked = properties.stage.sunModelEnabled; elZoneKeyLightColorRed.value = properties.keyLightColor.red; elZoneKeyLightColorGreen.value = properties.keyLightColor.green; elZoneKeyLightColorBlue.value = properties.keyLightColor.blue; @@ -477,11 +477,11 @@ elZoneKeyLightDirectionY.value = properties.keyLightDirection.y.toFixed(2); elZoneKeyLightDirectionZ.value = properties.keyLightDirection.z.toFixed(2); - elZoneStageLatitude.value = properties.stageLatitude.toFixed(2); - elZoneStageLongitude.value = properties.stageLongitude.toFixed(2); - elZoneStageAltitude.value = properties.stageAltitude.toFixed(2); - elZoneStageDay.value = properties.stageDay; - elZoneStageHour.value = properties.stageHour; + elZoneStageLatitude.value = properties.stage.latitude.toFixed(2); + elZoneStageLongitude.value = properties.stage.longitude.toFixed(2); + elZoneStageAltitude.value = properties.stage.altitude.toFixed(2); + elZoneStageDay.value = properties.stage.day; + elZoneStageHour.value = properties.stage.hour; elShapeType.value = properties.shapeType; elCompoundShapeURL.value = properties.compoundShapeURL; @@ -619,7 +619,7 @@ elTextBackgroundColorGreen.addEventListener('change', textBackgroundColorChangeFunction); elTextBackgroundColorBlue.addEventListener('change', textBackgroundColorChangeFunction); - elZoneStageSunModelEnabled.addEventListener('change', createEmitCheckedPropertyUpdateFunction('stageSunModelEnabled')); + elZoneStageSunModelEnabled.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('stage','sunModelEnabled')); var zoneKeyLightColorChangeFunction = createEmitColorPropertyUpdateFunction( 'keyLightColor', elZoneKeyLightColorRed, elZoneKeyLightColorGreen, elZoneKeyLightColorBlue); elZoneKeyLightColorRed.addEventListener('change', zoneKeyLightColorChangeFunction); @@ -633,11 +633,11 @@ elZoneKeyLightDirectionY.addEventListener('change', zoneKeyLightDirectionChangeFunction); elZoneKeyLightDirectionZ.addEventListener('change', zoneKeyLightDirectionChangeFunction); - elZoneStageLatitude.addEventListener('change', createEmitNumberPropertyUpdateFunction('stageLatitude')); - elZoneStageLongitude.addEventListener('change', createEmitNumberPropertyUpdateFunction('stageLongitude')); - elZoneStageAltitude.addEventListener('change', createEmitNumberPropertyUpdateFunction('stageAltitude')); - elZoneStageDay.addEventListener('change', createEmitNumberPropertyUpdateFunction('stageDay')); - elZoneStageHour.addEventListener('change', createEmitNumberPropertyUpdateFunction('stageHour')); + elZoneStageLatitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','latitude')); + elZoneStageLongitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','longitude')); + elZoneStageAltitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','altitude')); + elZoneStageDay.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','day')); + elZoneStageHour.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','hour')); elZoneBackgroundMode.addEventListener('change', createEmitTextPropertyUpdateFunction('backgroundMode')); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index e4c476c6f7..79606e687f 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -423,11 +423,11 @@ void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode, scene->setKeyLightIntensity(_bestZone->getKeyLightIntensity()); scene->setKeyLightAmbientIntensity(_bestZone->getKeyLightAmbientIntensity()); scene->setKeyLightDirection(_bestZone->getKeyLightDirection()); - scene->setStageSunModelEnable(_bestZone->getStageSunModelEnabled()); - scene->setStageLocation(_bestZone->getStageLongitude(), _bestZone->getStageLatitude(), - _bestZone->getStageAltitude()); - scene->setStageDayTime(_bestZone->getStageHour()); - scene->setStageYearTime(_bestZone->getStageDay()); + scene->setStageSunModelEnable(_bestZone->getStageProperties().getSunModelEnabled()); + scene->setStageLocation(_bestZone->getStageProperties().getLongitude(), _bestZone->getStageProperties().getLatitude(), + _bestZone->getStageProperties().getAltitude()); + scene->setStageDayTime(_bestZone->getStageProperties().getHour()); + scene->setStageYearTime(_bestZone->getStageProperties().getDay()); if (_bestZone->getBackgroundMode() == BACKGROUND_MODE_ATMOSPHERE) { EnvironmentData data = _bestZone->getEnvironmentData(); diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 0b3472fc09..ff54ef88fe 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -29,6 +29,7 @@ AtmospherePropertyGroup EntityItemProperties::_staticAtmosphere; SkyboxPropertyGroup EntityItemProperties::_staticSkybox; +StagePropertyGroup EntityItemProperties::_staticStage; EntityPropertyList PROP_LAST_ITEM = (EntityPropertyList)(PROP_AFTER_LAST_ITEM - 1); @@ -83,12 +84,6 @@ EntityItemProperties::EntityItemProperties() : CONSTRUCT_PROPERTY(keyLightIntensity, ZoneEntityItem::DEFAULT_KEYLIGHT_INTENSITY), CONSTRUCT_PROPERTY(keyLightAmbientIntensity, ZoneEntityItem::DEFAULT_KEYLIGHT_AMBIENT_INTENSITY), CONSTRUCT_PROPERTY(keyLightDirection, ZoneEntityItem::DEFAULT_KEYLIGHT_DIRECTION), - CONSTRUCT_PROPERTY(stageSunModelEnabled, ZoneEntityItem::DEFAULT_STAGE_SUN_MODEL_ENABLED), - CONSTRUCT_PROPERTY(stageLatitude, ZoneEntityItem::DEFAULT_STAGE_LATITUDE), - CONSTRUCT_PROPERTY(stageLongitude, ZoneEntityItem::DEFAULT_STAGE_LONGITUDE), - CONSTRUCT_PROPERTY(stageAltitude, ZoneEntityItem::DEFAULT_STAGE_ALTITUDE), - CONSTRUCT_PROPERTY(stageDay, ZoneEntityItem::DEFAULT_STAGE_DAY), - CONSTRUCT_PROPERTY(stageHour, ZoneEntityItem::DEFAULT_STAGE_HOUR), CONSTRUCT_PROPERTY(name, ENTITY_ITEM_DEFAULT_NAME), CONSTRUCT_PROPERTY(backgroundMode, BACKGROUND_MODE_INHERIT), @@ -332,15 +327,9 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_INTENSITY, keyLightIntensity); CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_AMBIENT_INTENSITY, keyLightAmbientIntensity); CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_DIRECTION, keyLightDirection); - CHECK_PROPERTY_CHANGE(PROP_STAGE_SUN_MODEL_ENABLED, stageSunModelEnabled); - CHECK_PROPERTY_CHANGE(PROP_STAGE_LATITUDE, stageLatitude); - CHECK_PROPERTY_CHANGE(PROP_STAGE_LONGITUDE, stageLongitude); - CHECK_PROPERTY_CHANGE(PROP_STAGE_ALTITUDE, stageAltitude); - CHECK_PROPERTY_CHANGE(PROP_STAGE_DAY, stageDay); - CHECK_PROPERTY_CHANGE(PROP_STAGE_HOUR, stageHour); - CHECK_PROPERTY_CHANGE(PROP_BACKGROUND_MODE, backgroundMode); - + + changedProperties += _stage.getChangedProperties(); changedProperties += _atmosphere.getChangedProperties(); changedProperties += _skybox.getChangedProperties(); @@ -419,12 +408,6 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(keyLightIntensity); COPY_PROPERTY_TO_QSCRIPTVALUE(keyLightAmbientIntensity); COPY_PROPERTY_TO_QSCRIPTVALUE_VEC3(keyLightDirection); - COPY_PROPERTY_TO_QSCRIPTVALUE(stageSunModelEnabled); - COPY_PROPERTY_TO_QSCRIPTVALUE(stageLatitude); - COPY_PROPERTY_TO_QSCRIPTVALUE(stageLongitude); - COPY_PROPERTY_TO_QSCRIPTVALUE(stageAltitude); - COPY_PROPERTY_TO_QSCRIPTVALUE(stageDay); - COPY_PROPERTY_TO_QSCRIPTVALUE(stageHour); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(backgroundMode, getBackgroundModeAsString()); // Sitting properties support @@ -460,6 +443,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(originalTextures, textureNamesList); // gettable, but not settable } + _stage.copyToScriptValue(properties, engine, skipDefaults, defaultEntityProperties); _atmosphere.copyToScriptValue(properties, engine, skipDefaults, defaultEntityProperties); _skybox.copyToScriptValue(properties, engine, skipDefaults, defaultEntityProperties); @@ -525,13 +509,9 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) { COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(keyLightIntensity, setKeyLightIntensity); COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(keyLightAmbientIntensity, setKeyLightAmbientIntensity); COPY_PROPERTY_FROM_QSCRIPTVALUE_VEC3(keyLightDirection, setKeyLightDirection); - COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL(stageSunModelEnabled, setStageSunModelEnabled); - COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(stageLatitude, setStageLatitude); - COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(stageLongitude, setStageLongitude); - COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(stageAltitude, setStageAltitude); - COPY_PROPERTY_FROM_QSCRIPTVALUE_INT(stageDay, setStageDay); - COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(stageHour, setStageHour); COPY_PROPERTY_FROM_QSCRITPTVALUE_ENUM(backgroundMode, BackgroundMode); + + _stage.copyFromScriptValue(object, _defaultSettings); _atmosphere.copyFromScriptValue(object, _defaultSettings); _skybox.copyFromScriptValue(object, _defaultSettings); _lastEdited = usecTimestampNow(); @@ -729,13 +709,10 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, appendValue, properties.getKeyLightIntensity()); APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_AMBIENT_INTENSITY, appendValue, properties.getKeyLightAmbientIntensity()); APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, appendValue, properties.getKeyLightDirection()); - APPEND_ENTITY_PROPERTY(PROP_STAGE_SUN_MODEL_ENABLED, appendValue, properties.getStageSunModelEnabled()); - APPEND_ENTITY_PROPERTY(PROP_STAGE_LATITUDE, appendValue, properties.getStageLatitude()); - APPEND_ENTITY_PROPERTY(PROP_STAGE_LONGITUDE, appendValue, properties.getStageLongitude()); - APPEND_ENTITY_PROPERTY(PROP_STAGE_ALTITUDE, appendValue, properties.getStageAltitude()); - APPEND_ENTITY_PROPERTY(PROP_STAGE_DAY, appendValue, properties.getStageDay()); - APPEND_ENTITY_PROPERTY(PROP_STAGE_HOUR, appendValue, properties.getStageHour()); - + + _staticStage.setProperties(properties); + _staticStage.appentToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState ); + APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, appendValue, (uint32_t)properties.getShapeType()); APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, appendValue, properties.getCompoundShapeURL()); @@ -987,12 +964,9 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_KEYLIGHT_INTENSITY, float, setKeyLightIntensity); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_KEYLIGHT_AMBIENT_INTENSITY, float, setKeyLightAmbientIntensity); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_KEYLIGHT_DIRECTION, glm::vec3, setKeyLightDirection); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_STAGE_SUN_MODEL_ENABLED, bool, setStageSunModelEnabled); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_STAGE_LATITUDE, float, setStageLatitude); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_STAGE_LONGITUDE, float, setStageLongitude); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_STAGE_ALTITUDE, float, setStageAltitude); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_STAGE_DAY, quint16, setStageDay); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_STAGE_HOUR, float, setStageHour); + + properties.getStage().decodeFromEditPacket(propertyFlags, dataAt , processedBytes); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SHAPE_TYPE, ShapeType, setShapeType); READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_COMPOUND_SHAPE_URL, setCompoundShapeURL); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BACKGROUND_MODE, BackgroundMode, setBackgroundMode); @@ -1093,14 +1067,9 @@ void EntityItemProperties::markAllChanged() { _keyLightIntensityChanged = true; _keyLightAmbientIntensityChanged = true; _keyLightDirectionChanged = true; - _stageSunModelEnabledChanged = true; - _stageLatitudeChanged = true; - _stageLongitudeChanged = true; - _stageAltitudeChanged = true; - _stageDayChanged = true; - _stageHourChanged = true; _backgroundModeChanged = true; + _stage.markAllChanged(); _atmosphere.markAllChanged(); _skybox.markAllChanged(); diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 13b2377032..0accdf0899 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -30,11 +30,12 @@ #include #include "AtmospherePropertyGroup.h" -#include "SkyboxPropertyGroup.h" #include "EntityItemID.h" #include "EntityItemPropertiesMacros.h" #include "EntityTypes.h" #include "EntityPropertyFlags.h" +#include "SkyboxPropertyGroup.h" +#include "StagePropertyGroup.h" const quint64 UNKNOWN_CREATED_TIME = 0; @@ -132,14 +133,9 @@ public: DEFINE_PROPERTY(PROP_KEYLIGHT_INTENSITY, KeyLightIntensity, keyLightIntensity, float); DEFINE_PROPERTY(PROP_KEYLIGHT_AMBIENT_INTENSITY, KeyLightAmbientIntensity, keyLightAmbientIntensity, float); DEFINE_PROPERTY_REF(PROP_KEYLIGHT_DIRECTION, KeyLightDirection, keyLightDirection, glm::vec3); - DEFINE_PROPERTY(PROP_STAGE_SUN_MODEL_ENABLED, StageSunModelEnabled, stageSunModelEnabled, bool); - DEFINE_PROPERTY(PROP_STAGE_LATITUDE, StageLatitude, stageLatitude, float); - DEFINE_PROPERTY(PROP_STAGE_LONGITUDE, StageLongitude, stageLongitude, float); - DEFINE_PROPERTY(PROP_STAGE_ALTITUDE, StageAltitude, stageAltitude, float); - DEFINE_PROPERTY(PROP_STAGE_DAY, StageDay, stageDay, quint16); - DEFINE_PROPERTY(PROP_STAGE_HOUR, StageHour, stageHour, float); DEFINE_PROPERTY_REF(PROP_NAME, Name, name, QString); DEFINE_PROPERTY_REF_ENUM(PROP_BACKGROUND_MODE, BackgroundMode, backgroundMode, BackgroundMode); + DEFINE_PROPERTY_GROUP(Stage, stage, StagePropertyGroup); DEFINE_PROPERTY_GROUP(Atmosphere, atmosphere, AtmospherePropertyGroup); DEFINE_PROPERTY_GROUP(Skybox, skybox, SkyboxPropertyGroup); @@ -280,6 +276,7 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) { DEBUG_PROPERTY_IF_CHANGED(debug, properties, MarketplaceID, marketplaceID, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, BackgroundMode, backgroundMode, ""); + properties.getStage().debugDump(); properties.getAtmosphere().debugDump(); properties.getSkybox().debugDump(); diff --git a/libraries/entities/src/EntityItemPropertiesMacros.h b/libraries/entities/src/EntityItemPropertiesMacros.h index 1b10b6eb7a..b93e0e211d 100644 --- a/libraries/entities/src/EntityItemPropertiesMacros.h +++ b/libraries/entities/src/EntityItemPropertiesMacros.h @@ -316,6 +316,20 @@ } \ } +#define COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_UINT16(G, P, S) \ + { \ + QScriptValue G = object.property(#G); \ + if (G.isValid()) { \ + QScriptValue P = G.property(#P); \ + if (P.isValid()) { \ + uint16_t newValue = P.toVariant().toInt(); \ + if (_defaultSettings || newValue != _##P) { \ + S(newValue); \ + } \ + } \ + } \ + } + #define COPY_PROPERTY_FROM_QSCRIPTVALUE_INT(P, S) \ QScriptValue P = object.property(#P); \ if (P.isValid()) { \ diff --git a/libraries/entities/src/StagePropertyGroup.cpp b/libraries/entities/src/StagePropertyGroup.cpp new file mode 100644 index 0000000000..e65a64ba77 --- /dev/null +++ b/libraries/entities/src/StagePropertyGroup.cpp @@ -0,0 +1,198 @@ +// +// StagePropertyGroup.cpp +// libraries/entities/src +// +// Created by Brad Hefta-Gaub on 12/4/13. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include + +#include "StagePropertyGroup.h" +#include "EntityItemProperties.h" +#include "EntityItemPropertiesMacros.h" + +const bool StagePropertyGroup::DEFAULT_STAGE_SUN_MODEL_ENABLED = false; +const float StagePropertyGroup::DEFAULT_STAGE_LATITUDE = 37.777f; +const float StagePropertyGroup::DEFAULT_STAGE_LONGITUDE = 122.407f; +const float StagePropertyGroup::DEFAULT_STAGE_ALTITUDE = 0.03f; +const quint16 StagePropertyGroup::DEFAULT_STAGE_DAY = 60; +const float StagePropertyGroup::DEFAULT_STAGE_HOUR = 12.0f; + +StagePropertyGroup::StagePropertyGroup() { + _sunModelEnabled = DEFAULT_STAGE_SUN_MODEL_ENABLED; + _latitude = DEFAULT_STAGE_LATITUDE; + _longitude = DEFAULT_STAGE_LONGITUDE; + _altitude = DEFAULT_STAGE_ALTITUDE; + _day = DEFAULT_STAGE_DAY; + _hour = DEFAULT_STAGE_HOUR; +} + +void StagePropertyGroup::copyToScriptValue(QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const { + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Stage, stage, SunModelEnabled, sunModelEnabled); + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Stage, stage, Latitude, latitude); + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Stage, stage, Longitude, longitude); + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Stage, stage, Altitude, altitude); + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Stage, stage, Day, day); + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Stage, stage, Hour, hour); +} + +void StagePropertyGroup::copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) { + COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_BOOL(stage, sunModelEnabled, setSunModelEnabled); + COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(stage, latitude, setLatitude); + COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(stage, longitude, setLongitude); + COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(stage, altitude, setAltitude); + COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_UINT16(stage, day, setDay); + COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(stage, hour, setHour); +} + +void StagePropertyGroup::debugDump() const { + qDebug() << " StagePropertyGroup: ---------------------------------------------"; + qDebug() << " _sunModelEnabled:" << _sunModelEnabled; + qDebug() << " _latitude:" << _latitude; + qDebug() << " _longitude:" << _longitude; + qDebug() << " _altitude:" << _altitude; + qDebug() << " _day:" << _day; + qDebug() << " _hour:" << _hour; + +} + +bool StagePropertyGroup::appentToEditPacket(OctreePacketData* packetData, + EntityPropertyFlags& requestedProperties, + EntityPropertyFlags& propertyFlags, + EntityPropertyFlags& propertiesDidntFit, + int& propertyCount, + OctreeElement::AppendState& appendState) const { + + bool successPropertyFits = true; + + APPEND_ENTITY_PROPERTY(PROP_STAGE_SUN_MODEL_ENABLED, appendValue, getSunModelEnabled()); + APPEND_ENTITY_PROPERTY(PROP_STAGE_LATITUDE, appendValue, getLatitude()); + APPEND_ENTITY_PROPERTY(PROP_STAGE_LONGITUDE, appendValue, getLongitude()); + APPEND_ENTITY_PROPERTY(PROP_STAGE_ALTITUDE, appendValue, getAltitude()); + APPEND_ENTITY_PROPERTY(PROP_STAGE_DAY, appendValue, getDay()); + APPEND_ENTITY_PROPERTY(PROP_STAGE_HOUR, appendValue, getHour()); + + return true; +} + + +bool StagePropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFlags, const unsigned char*& dataAt , int& processedBytes) { + + int bytesRead = 0; + bool overwriteLocalData = true; + + READ_ENTITY_PROPERTY(PROP_STAGE_SUN_MODEL_ENABLED, bool, _sunModelEnabled); + READ_ENTITY_PROPERTY(PROP_STAGE_LATITUDE, float, _latitude); + READ_ENTITY_PROPERTY(PROP_STAGE_LONGITUDE, float, _longitude); + READ_ENTITY_PROPERTY(PROP_STAGE_ALTITUDE, float, _altitude); + READ_ENTITY_PROPERTY(PROP_STAGE_DAY, quint16, _day); + READ_ENTITY_PROPERTY(PROP_STAGE_HOUR, float, _hour); + + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_STAGE_SUN_MODEL_ENABLED, SunModelEnabled); + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_STAGE_LATITUDE, Latitude); + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_STAGE_LONGITUDE, Longitude); + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_STAGE_ALTITUDE, Altitude); + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_STAGE_DAY, Day); + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_STAGE_HOUR, Hour); + + processedBytes += bytesRead; + + return true; +} + +void StagePropertyGroup::markAllChanged() { + _sunModelEnabledChanged = true; + _latitudeChanged = true; + _longitudeChanged = true; + _altitudeChanged = true; + _dayChanged = true; + _hourChanged = true; +} + +EntityPropertyFlags StagePropertyGroup::getChangedProperties() const { + EntityPropertyFlags changedProperties; + + CHECK_PROPERTY_CHANGE(PROP_STAGE_SUN_MODEL_ENABLED, sunModelEnabled); + CHECK_PROPERTY_CHANGE(PROP_STAGE_LATITUDE, latitude); + CHECK_PROPERTY_CHANGE(PROP_STAGE_LONGITUDE, longitude); + CHECK_PROPERTY_CHANGE(PROP_STAGE_ALTITUDE, altitude); + CHECK_PROPERTY_CHANGE(PROP_STAGE_DAY, day); + CHECK_PROPERTY_CHANGE(PROP_STAGE_HOUR, hour); + + return changedProperties; +} + +void StagePropertyGroup::getProperties(EntityItemProperties& properties) const { + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Stage, SunModelEnabled, getSunModelEnabled); + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Stage, Latitude, getLatitude); + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Stage, Longitude, getLongitude); + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Stage, Altitude, getAltitude); + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Stage, Day, getDay); + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Stage, Hour, getHour); +} + +bool StagePropertyGroup::setProperties(const EntityItemProperties& properties) { + bool somethingChanged = false; + + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Stage, SunModelEnabled, sunModelEnabled, setSunModelEnabled); + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Stage, Latitude, latitude, setLatitude); + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Stage, Longitude, longitude, setLongitude); + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Stage, Altitude, altitude, setAltitude); + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Stage, Day, day, setDay); + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Stage, Hour, hour, setHour); + + return somethingChanged; +} + +EntityPropertyFlags StagePropertyGroup::getEntityProperties(EncodeBitstreamParams& params) const { + EntityPropertyFlags requestedProperties; + + requestedProperties += PROP_STAGE_SUN_MODEL_ENABLED; + requestedProperties += PROP_STAGE_LATITUDE; + requestedProperties += PROP_STAGE_LONGITUDE; + requestedProperties += PROP_STAGE_ALTITUDE; + requestedProperties += PROP_STAGE_DAY; + requestedProperties += PROP_STAGE_HOUR; + + return requestedProperties; +} + +void StagePropertyGroup::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, + EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData, + EntityPropertyFlags& requestedProperties, + EntityPropertyFlags& propertyFlags, + EntityPropertyFlags& propertiesDidntFit, + int& propertyCount, + OctreeElement::AppendState& appendState) const { + + bool successPropertyFits = true; + + APPEND_ENTITY_PROPERTY(PROP_STAGE_SUN_MODEL_ENABLED, appendValue, getSunModelEnabled()); + APPEND_ENTITY_PROPERTY(PROP_STAGE_LATITUDE, appendValue, getLatitude()); + APPEND_ENTITY_PROPERTY(PROP_STAGE_LONGITUDE, appendValue, getLongitude()); + APPEND_ENTITY_PROPERTY(PROP_STAGE_ALTITUDE, appendValue, getAltitude()); + APPEND_ENTITY_PROPERTY(PROP_STAGE_DAY, appendValue, getDay()); + APPEND_ENTITY_PROPERTY(PROP_STAGE_HOUR, appendValue, getHour()); + +} + +int StagePropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, + ReadBitstreamToTreeParams& args, + EntityPropertyFlags& propertyFlags, bool overwriteLocalData) { + + int bytesRead = 0; + const unsigned char* dataAt = data; + + READ_ENTITY_PROPERTY(PROP_STAGE_SUN_MODEL_ENABLED, bool, _sunModelEnabled); + READ_ENTITY_PROPERTY(PROP_STAGE_LATITUDE, float, _latitude); + READ_ENTITY_PROPERTY(PROP_STAGE_LONGITUDE, float, _longitude); + READ_ENTITY_PROPERTY(PROP_STAGE_ALTITUDE, float, _altitude); + READ_ENTITY_PROPERTY(PROP_STAGE_DAY, quint16, _day); + READ_ENTITY_PROPERTY(PROP_STAGE_HOUR, float, _hour); + + return bytesRead; +} diff --git a/libraries/entities/src/StagePropertyGroup.h b/libraries/entities/src/StagePropertyGroup.h new file mode 100644 index 0000000000..3a1adb1c88 --- /dev/null +++ b/libraries/entities/src/StagePropertyGroup.h @@ -0,0 +1,87 @@ +// +// StagePropertyGroup.h +// libraries/entities/src +// +// Created by Brad Hefta-Gaub on 12/4/13. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_StagePropertyGroup_h +#define hifi_StagePropertyGroup_h + +#include + +#include "PropertyGroup.h" +#include "EntityItemPropertiesMacros.h" + +class EntityItemProperties; +class EncodeBitstreamParams; +class OctreePacketData; +class EntityTreeElementExtraEncodeData; +class ReadBitstreamToTreeParams; + +#include +#include + + +class StagePropertyGroup : public PropertyGroup { +public: + StagePropertyGroup(); + virtual ~StagePropertyGroup() {} + + // EntityItemProperty related helpers + virtual void copyToScriptValue(QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const; + virtual void copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings); + virtual void debugDump() const; + + virtual bool appentToEditPacket(OctreePacketData* packetData, + EntityPropertyFlags& requestedProperties, + EntityPropertyFlags& propertyFlags, + EntityPropertyFlags& propertiesDidntFit, + int& propertyCount, + OctreeElement::AppendState& appendState) const; + + virtual bool decodeFromEditPacket(EntityPropertyFlags& propertyFlags, const unsigned char*& dataAt , int& processedBytes); + virtual void markAllChanged(); + virtual EntityPropertyFlags getChangedProperties() const; + + // EntityItem related helpers + // methods for getting/setting all properties of an entity + virtual void getProperties(EntityItemProperties& propertiesOut) const; + + /// returns true if something changed + virtual bool setProperties(const EntityItemProperties& properties); + + virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const; + + virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, + EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData, + EntityPropertyFlags& requestedProperties, + EntityPropertyFlags& propertyFlags, + EntityPropertyFlags& propertiesDidntFit, + int& propertyCount, + OctreeElement::AppendState& appendState) const; + + virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, + ReadBitstreamToTreeParams& args, + EntityPropertyFlags& propertyFlags, bool overwriteLocalData); + + static const bool DEFAULT_STAGE_SUN_MODEL_ENABLED; + static const float DEFAULT_STAGE_LATITUDE; + static const float DEFAULT_STAGE_LONGITUDE; + static const float DEFAULT_STAGE_ALTITUDE; + static const quint16 DEFAULT_STAGE_DAY; + static const float DEFAULT_STAGE_HOUR; + + DEFINE_PROPERTY(PROP_STAGE_SUN_MODEL_ENABLED, SunModelEnabled, sunModelEnabled, bool); + DEFINE_PROPERTY(PROP_STAGE_LATITUDE, Latitude, latitude, float); + DEFINE_PROPERTY(PROP_STAGE_LONGITUDE, Longitude, longitude, float); + DEFINE_PROPERTY(PROP_STAGE_ALTITUDE, Altitude, altitude, float); + DEFINE_PROPERTY(PROP_STAGE_DAY, Day, day, uint16_t); + DEFINE_PROPERTY(PROP_STAGE_HOUR, Hour, hour, float); +}; + +#endif // hifi_StagePropertyGroup_h diff --git a/libraries/entities/src/ZoneEntityItem.cpp b/libraries/entities/src/ZoneEntityItem.cpp index f8e8eceb9f..b85c543ce4 100644 --- a/libraries/entities/src/ZoneEntityItem.cpp +++ b/libraries/entities/src/ZoneEntityItem.cpp @@ -26,12 +26,6 @@ const xColor ZoneEntityItem::DEFAULT_KEYLIGHT_COLOR = { 255, 255, 255 }; const float ZoneEntityItem::DEFAULT_KEYLIGHT_INTENSITY = 1.0f; const float ZoneEntityItem::DEFAULT_KEYLIGHT_AMBIENT_INTENSITY = 0.5f; const glm::vec3 ZoneEntityItem::DEFAULT_KEYLIGHT_DIRECTION = { 0.0f, -1.0f, 0.0f }; -const bool ZoneEntityItem::DEFAULT_STAGE_SUN_MODEL_ENABLED = false; -const float ZoneEntityItem::DEFAULT_STAGE_LATITUDE = 37.777f; -const float ZoneEntityItem::DEFAULT_STAGE_LONGITUDE = 122.407f; -const float ZoneEntityItem::DEFAULT_STAGE_ALTITUDE = 0.03f; -const quint16 ZoneEntityItem::DEFAULT_STAGE_DAY = 60; -const float ZoneEntityItem::DEFAULT_STAGE_HOUR = 12.0f; const ShapeType ZoneEntityItem::DEFAULT_SHAPE_TYPE = SHAPE_TYPE_BOX; const QString ZoneEntityItem::DEFAULT_COMPOUND_SHAPE_URL = ""; @@ -53,12 +47,6 @@ ZoneEntityItem::ZoneEntityItem(const EntityItemID& entityItemID, const EntityIte _keyLightIntensity = DEFAULT_KEYLIGHT_INTENSITY; _keyLightAmbientIntensity = DEFAULT_KEYLIGHT_AMBIENT_INTENSITY; _keyLightDirection = DEFAULT_KEYLIGHT_DIRECTION; - _stageSunModelEnabled = DEFAULT_STAGE_SUN_MODEL_ENABLED; - _stageLatitude = DEFAULT_STAGE_LATITUDE; - _stageLongitude = DEFAULT_STAGE_LONGITUDE; - _stageAltitude = DEFAULT_STAGE_ALTITUDE; - _stageDay = DEFAULT_STAGE_DAY; - _stageHour = DEFAULT_STAGE_HOUR; _shapeType = DEFAULT_SHAPE_TYPE; _compoundShapeURL = DEFAULT_COMPOUND_SHAPE_URL; @@ -94,15 +82,11 @@ EntityItemProperties ZoneEntityItem::getProperties() const { COPY_ENTITY_PROPERTY_TO_PROPERTIES(keyLightIntensity, getKeyLightIntensity); COPY_ENTITY_PROPERTY_TO_PROPERTIES(keyLightAmbientIntensity, getKeyLightAmbientIntensity); COPY_ENTITY_PROPERTY_TO_PROPERTIES(keyLightDirection, getKeyLightDirection); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(stageSunModelEnabled, getStageSunModelEnabled); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(stageLatitude, getStageLatitude); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(stageLongitude, getStageLongitude); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(stageAltitude, getStageAltitude); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(stageDay, getStageDay); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(stageHour, getStageHour); + + _stageProperties.getProperties(properties); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(shapeType, getShapeType); COPY_ENTITY_PROPERTY_TO_PROPERTIES(compoundShapeURL, getCompoundShapeURL); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(backgroundMode, getBackgroundMode); _atmosphereProperties.getProperties(properties); @@ -119,12 +103,9 @@ bool ZoneEntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(keyLightIntensity, setKeyLightIntensity); SET_ENTITY_PROPERTY_FROM_PROPERTIES(keyLightAmbientIntensity, setKeyLightAmbientIntensity); SET_ENTITY_PROPERTY_FROM_PROPERTIES(keyLightDirection, setKeyLightDirection); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(stageSunModelEnabled, setStageSunModelEnabled); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(stageLatitude, setStageLatitude); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(stageLongitude, setStageLongitude); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(stageAltitude, setStageAltitude); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(stageDay, setStageDay); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(stageHour, setStageHour); + + bool somethingChangedInStage = _stageProperties.setProperties(properties); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(shapeType, updateShapeType); SET_ENTITY_PROPERTY_FROM_PROPERTIES(compoundShapeURL, setCompoundShapeURL); SET_ENTITY_PROPERTY_FROM_PROPERTIES(backgroundMode, setBackgroundMode); @@ -132,7 +113,7 @@ bool ZoneEntityItem::setProperties(const EntityItemProperties& properties) { bool somethingChangedInAtmosphere = _atmosphereProperties.setProperties(properties); bool somethingChangedInSkybox = _skyboxProperties.setProperties(properties); - somethingChanged = somethingChanged || somethingChangedInAtmosphere || somethingChangedInSkybox; + somethingChanged = somethingChanged || somethingChangedInStage || somethingChangedInAtmosphere || somethingChangedInSkybox; if (somethingChanged) { bool wantDebug = false; @@ -158,12 +139,13 @@ int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, READ_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, float, _keyLightIntensity); READ_ENTITY_PROPERTY(PROP_KEYLIGHT_AMBIENT_INTENSITY, float, _keyLightAmbientIntensity); READ_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, glm::vec3, _keyLightDirection); - READ_ENTITY_PROPERTY(PROP_STAGE_SUN_MODEL_ENABLED, bool, _stageSunModelEnabled); - READ_ENTITY_PROPERTY(PROP_STAGE_LATITUDE, float, _stageLatitude); - READ_ENTITY_PROPERTY(PROP_STAGE_LONGITUDE, float, _stageLongitude); - READ_ENTITY_PROPERTY(PROP_STAGE_ALTITUDE, float, _stageAltitude); - READ_ENTITY_PROPERTY(PROP_STAGE_DAY, quint16, _stageDay); - READ_ENTITY_PROPERTY(PROP_STAGE_HOUR, float, _stageHour); + + int bytesFromStage = _stageProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, + propertyFlags, overwriteLocalData); + + bytesRead += bytesFromStage; + dataAt += bytesFromStage; + READ_ENTITY_PROPERTY_SETTER(PROP_SHAPE_TYPE, ShapeType, updateShapeType); READ_ENTITY_PROPERTY_STRING(PROP_COMPOUND_SHAPE_URL, setCompoundShapeURL); READ_ENTITY_PROPERTY_SETTER(PROP_BACKGROUND_MODE, BackgroundMode, setBackgroundMode); @@ -191,15 +173,10 @@ EntityPropertyFlags ZoneEntityItem::getEntityProperties(EncodeBitstreamParams& p requestedProperties += PROP_KEYLIGHT_INTENSITY; requestedProperties += PROP_KEYLIGHT_AMBIENT_INTENSITY; requestedProperties += PROP_KEYLIGHT_DIRECTION; - requestedProperties += PROP_STAGE_SUN_MODEL_ENABLED; - requestedProperties += PROP_STAGE_LATITUDE; - requestedProperties += PROP_STAGE_LONGITUDE; - requestedProperties += PROP_STAGE_ALTITUDE; - requestedProperties += PROP_STAGE_DAY; - requestedProperties += PROP_STAGE_HOUR; requestedProperties += PROP_SHAPE_TYPE; requestedProperties += PROP_COMPOUND_SHAPE_URL; requestedProperties += PROP_BACKGROUND_MODE; + requestedProperties += _stageProperties.getEntityProperties(params); requestedProperties += _atmosphereProperties.getEntityProperties(params); requestedProperties += _skyboxProperties.getEntityProperties(params); @@ -220,12 +197,11 @@ void ZoneEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, appendValue, getKeyLightIntensity()); APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_AMBIENT_INTENSITY, appendValue, getKeyLightAmbientIntensity()); APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, appendValue, getKeyLightDirection()); - APPEND_ENTITY_PROPERTY(PROP_STAGE_SUN_MODEL_ENABLED, appendValue, getStageSunModelEnabled()); - APPEND_ENTITY_PROPERTY(PROP_STAGE_LATITUDE, appendValue, getStageLatitude()); - APPEND_ENTITY_PROPERTY(PROP_STAGE_LONGITUDE, appendValue, getStageLongitude()); - APPEND_ENTITY_PROPERTY(PROP_STAGE_ALTITUDE, appendValue, getStageAltitude()); - APPEND_ENTITY_PROPERTY(PROP_STAGE_DAY, appendValue, getStageDay()); - APPEND_ENTITY_PROPERTY(PROP_STAGE_HOUR, appendValue, getStageHour()); + + _stageProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties, + propertyFlags, propertiesDidntFit, propertyCount, appendState); + + APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, appendValue, (uint32_t)getShapeType()); APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, appendValue, getCompoundShapeURL()); APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_MODE, appendValue, (uint32_t)getBackgroundMode()); // could this be a uint16?? @@ -248,14 +224,9 @@ void ZoneEntityItem::debugDump() const { qCDebug(entities) << " _keyLightIntensity:" << _keyLightIntensity; qCDebug(entities) << " _keyLightAmbientIntensity:" << _keyLightAmbientIntensity; qCDebug(entities) << " _keyLightDirection:" << _keyLightDirection; - qCDebug(entities) << " _stageSunModelEnabled:" << _stageSunModelEnabled; - qCDebug(entities) << " _stageLatitude:" << _stageLatitude; - qCDebug(entities) << " _stageLongitude:" << _stageLongitude; - qCDebug(entities) << " _stageAltitude:" << _stageAltitude; - qCDebug(entities) << " _stageDay:" << _stageDay; - qCDebug(entities) << " _stageHour:" << _stageHour; qCDebug(entities) << " _backgroundMode:" << EntityItemProperties::getBackgroundModeString(_backgroundMode); + _stageProperties.debugDump(); _atmosphereProperties.debugDump(); _skyboxProperties.debugDump(); } diff --git a/libraries/entities/src/ZoneEntityItem.h b/libraries/entities/src/ZoneEntityItem.h index 6c67ea72dd..4388bf908a 100644 --- a/libraries/entities/src/ZoneEntityItem.h +++ b/libraries/entities/src/ZoneEntityItem.h @@ -69,24 +69,6 @@ public: const glm::vec3& getKeyLightDirection() const { return _keyLightDirection; } void setKeyLightDirection(const glm::vec3& value) { _keyLightDirection = value; } - bool getStageSunModelEnabled() const { return _stageSunModelEnabled; } - void setStageSunModelEnabled(bool value) { _stageSunModelEnabled = value; } - - float getStageLatitude() const { return _stageLatitude; } - void setStageLatitude(float value) { _stageLatitude = value; } - - float getStageLongitude() const { return _stageLongitude; } - void setStageLongitude(float value) { _stageLongitude = value; } - - float getStageAltitude() const { return _stageAltitude; } - void setStageAltitude(float value) { _stageAltitude = value; } - - uint16_t getStageDay() const { return _stageDay; } - void setStageDay(uint16_t value) { _stageDay = value; } - - float getStageHour() const { return _stageHour; } - void setStageHour(float value) { _stageHour = value; } - static bool getZonesArePickable() { return _zonesArePickable; } static void setZonesArePickable(bool value) { _zonesArePickable = value; } @@ -107,6 +89,7 @@ public: EnvironmentData getEnvironmentData() const; const AtmospherePropertyGroup& getAtmosphereProperties() const { return _atmosphereProperties; } const SkyboxPropertyGroup& getSkyboxProperties() const { return _skyboxProperties; } + const StagePropertyGroup& getStageProperties() const { return _stageProperties; } virtual bool supportsDetailedRayIntersection() const { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, @@ -119,12 +102,6 @@ public: static const float DEFAULT_KEYLIGHT_INTENSITY; static const float DEFAULT_KEYLIGHT_AMBIENT_INTENSITY; static const glm::vec3 DEFAULT_KEYLIGHT_DIRECTION; - static const bool DEFAULT_STAGE_SUN_MODEL_ENABLED; - static const float DEFAULT_STAGE_LATITUDE; - static const float DEFAULT_STAGE_LONGITUDE; - static const float DEFAULT_STAGE_ALTITUDE; - static const quint16 DEFAULT_STAGE_DAY; - static const float DEFAULT_STAGE_HOUR; static const ShapeType DEFAULT_SHAPE_TYPE; static const QString DEFAULT_COMPOUND_SHAPE_URL; @@ -134,17 +111,13 @@ protected: float _keyLightIntensity; float _keyLightAmbientIntensity; glm::vec3 _keyLightDirection; - bool _stageSunModelEnabled; - float _stageLatitude; - float _stageLongitude; - float _stageAltitude; - uint16_t _stageDay; - float _stageHour; ShapeType _shapeType = DEFAULT_SHAPE_TYPE; QString _compoundShapeURL; BackgroundMode _backgroundMode = BACKGROUND_MODE_INHERIT; + + StagePropertyGroup _stageProperties; AtmospherePropertyGroup _atmosphereProperties; SkyboxPropertyGroup _skyboxProperties; From c0a71da9e385ff3dfb0d32d4ada282330878da35 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Sat, 9 May 2015 13:16:34 -0700 Subject: [PATCH 22/39] Handle empty face groups, such as in the rama cyclinder that crashed the Friday meeting (http://headache.hungry.com/~seth/hifi/stickCollisionModel.obj). --- libraries/fbx/src/OBJReader.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index c26dcacd4c..4a8a2fc53d 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -386,8 +386,9 @@ bool OBJReader::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mappi done: if (faces.count() == 0) { // empty mesh mesh.parts.pop_back(); + } else { + faceGroups.append(faces); // We're done with this group. Add the faces. } - faceGroups.append(faces); // We're done with this group. Add the faces. //qCDebug(modelformat) << "end group:" << meshPart.materialID << " original faces:" << originalFaceCountForDebugging << " triangles:" << faces.count() << " keep going:" << result; return result; } From 6337158cfcd4618858224335f660085cbce12ec9 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Sat, 9 May 2015 13:34:35 -0700 Subject: [PATCH 23/39] Fix "simple inline/"direct code injection" entity scripts fail to load" (https://app.asana.com/0/32622044445063/33562012389754) --- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index e4c476c6f7..c10d673890 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -142,7 +142,7 @@ QString EntityTreeRenderer::loadScriptContents(const QString& scriptMaybeURLorTe QUrl url(scriptMaybeURLorText); // If the url is not valid, this must be script text... - if (!url.isValid()) { + if (!url.isValid() || scriptMaybeURLorText.startsWith("(")) { isURL = false; return scriptMaybeURLorText; } From 70f7329a7e804430c3a71833e366fb9394c1486d Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 9 May 2015 17:59:10 -0700 Subject: [PATCH 24/39] Disable pragma that Windows doesn't know about --- libraries/networking/src/DataServerAccountInfo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/DataServerAccountInfo.cpp b/libraries/networking/src/DataServerAccountInfo.cpp index 44e8dbef90..aa9c5bed93 100644 --- a/libraries/networking/src/DataServerAccountInfo.cpp +++ b/libraries/networking/src/DataServerAccountInfo.cpp @@ -17,7 +17,7 @@ #include "NetworkLogging.h" #include "DataServerAccountInfo.h" -#ifndef __GNUC__ +#if !defined(__GNUC__) && !defined(Q_OS_WIN) #pragma clang diagnostic ignored "-Wdeprecated-declarations" #endif From 34deba7fffc294d27995002bc6e1821a1e95498d Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sat, 9 May 2015 17:59:45 -0700 Subject: [PATCH 25/39] undo mistaken change of setting name --- libraries/octree/src/OctreeQuery.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/octree/src/OctreeQuery.cpp b/libraries/octree/src/OctreeQuery.cpp index 5f62318338..6ca55fc4cc 100644 --- a/libraries/octree/src/OctreeQuery.cpp +++ b/libraries/octree/src/OctreeQuery.cpp @@ -16,7 +16,7 @@ #include "OctreeConstants.h" #include "OctreeQuery.h" -Setting::Handle maxOctreePacketsPerSecond("maxOctreePPSSpin", DEFAULT_MAX_OCTREE_PPS); +Setting::Handle maxOctreePacketsPerSecond("maxOctreePPS", DEFAULT_MAX_OCTREE_PPS); OctreeQuery::OctreeQuery() { _maxOctreePPS = maxOctreePacketsPerSecond.get(); From 8da3490a4cea5ac2c7ad101b57dc1f2540a22fb9 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sun, 10 May 2015 09:32:03 -0700 Subject: [PATCH 26/39] when grabbing an entity, zero out its gravity. --- examples/grab.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/examples/grab.js b/examples/grab.js index df2042350e..efacc26612 100644 --- a/examples/grab.js +++ b/examples/grab.js @@ -27,6 +27,7 @@ var ANGULAR_DAMPING_RATE = 0.40; var SCREEN_TO_METERS = 0.001; var currentPosition, currentVelocity, cameraEntityDistance, currentRotation; var velocityTowardTarget, desiredVelocity, addedVelocity, newVelocity, dPosition, camYaw, distanceToTarget, targetPosition; +var originalGravity; var shouldRotate = false; var dQ, theta, axisAngle, dT; var angularVelocity = { @@ -65,6 +66,7 @@ function mousePressEvent(event) { grabbedEntity = intersection.entityID; var props = Entities.getEntityProperties(grabbedEntity) isGrabbing = true; + originalGravity = props.gravity; targetPosition = props.position; currentPosition = props.position; currentVelocity = props.velocity; @@ -96,6 +98,11 @@ function updateDropLine(position) { function mouseReleaseEvent() { if (isGrabbing) { isGrabbing = false; + + Entities.editEntity(grabbedEntity, { + gravity: originalGravity + }); + Overlays.editOverlay(dropLine, { visible: false }); @@ -194,7 +201,7 @@ function update(deltaTime) { newVelocity = Vec3.subtract(newVelocity, Vec3.multiply(newVelocity, DAMPING_RATE)); // Update entity } else { - newVelocity = entityProps.velocity; + newVelocity = {x: 0, y: 0, z: 0}; } if (shouldRotate) { angularVelocity = Vec3.subtract(angularVelocity, Vec3.multiply(angularVelocity, ANGULAR_DAMPING_RATE)); @@ -204,7 +211,8 @@ function update(deltaTime) { Entities.editEntity(grabbedEntity, { velocity: newVelocity, - angularVelocity: angularVelocity + angularVelocity: angularVelocity, + gravity: {x: 0, y: 0, z: 0} }) updateDropLine(targetPosition); } @@ -215,4 +223,4 @@ Controller.mousePressEvent.connect(mousePressEvent); Controller.mouseReleaseEvent.connect(mouseReleaseEvent); Controller.keyPressEvent.connect(keyPressEvent); Controller.keyReleaseEvent.connect(keyReleaseEvent); -Script.update.connect(update); \ No newline at end of file +Script.update.connect(update); From 17c3c1a18d8c2fe8cb18ccfb22c925f4024daf73 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sun, 10 May 2015 15:22:02 -0700 Subject: [PATCH 27/39] add support for automatic hour/day calculations and backward compatibility on stage properties --- .../entities/changingAtmosphereExample.js | 14 +++-- .../example/entities/zoneAtmosphereExample.js | 14 +++-- .../example/entities/zoneEntityExample.js | 16 ++--- .../example/entities/zoneSkyboxExample.js | 14 +++-- examples/html/entityProperties.html | 11 ++++ .../src/EntityTreeRenderer.cpp | 4 +- .../entities/src/EntityItemPropertiesMacros.h | 28 +++++++++ libraries/entities/src/EntityPropertyFlags.h | 1 + libraries/entities/src/StagePropertyGroup.cpp | 63 ++++++++++++++++++- libraries/entities/src/StagePropertyGroup.h | 4 ++ libraries/networking/src/PacketHeaders.cpp | 2 +- libraries/networking/src/PacketHeaders.h | 1 + 12 files changed, 141 insertions(+), 31 deletions(-) diff --git a/examples/example/entities/changingAtmosphereExample.js b/examples/example/entities/changingAtmosphereExample.js index 88a25b6a08..02103fc0fb 100644 --- a/examples/example/entities/changingAtmosphereExample.js +++ b/examples/example/entities/changingAtmosphereExample.js @@ -35,12 +35,14 @@ var zoneEntityA = Entities.addEntity({ scatteringWavelengths: { x: 0.650, y: 0.570, z: 0.475 }, hasStars: true }, - stageLatitude: 37.777, - stageLongitude: 122.407, - stageAltitude: 0.03, - stageDay: 183, - stageHour: 5, - stageSunModelEnabled: true + stage: { + latitude: 37.777, + longitude: 122.407, + altitude: 0.03, + day: 183, + hour: 5, + sunModelEnabled: true + } }); diff --git a/examples/example/entities/zoneAtmosphereExample.js b/examples/example/entities/zoneAtmosphereExample.js index b31a453300..dfebf09f2a 100644 --- a/examples/example/entities/zoneAtmosphereExample.js +++ b/examples/example/entities/zoneAtmosphereExample.js @@ -33,12 +33,14 @@ var zoneEntityA = Entities.addEntity({ scatteringWavelengths: { x: 0.650, y: 0.570, z: 0.475 }, hasStars: false }, - stageLatitude: 37.777, - stageLongitude: 122.407, - stageAltitude: 0.03, - stageDay: 60, - stageHour: 0, - stageSunModelEnabled: true + stage: { + latitude: 37.777, + longitude: 122.407, + altitude: 0.03, + day: 60, + hour: 0, + sunModelEnabled: true + } }); diff --git a/examples/example/entities/zoneEntityExample.js b/examples/example/entities/zoneEntityExample.js index b5831a2bb5..2d8b587d53 100644 --- a/examples/example/entities/zoneEntityExample.js +++ b/examples/example/entities/zoneEntityExample.js @@ -34,17 +34,18 @@ var zoneEntityB = Entities.addEntity({ dimensions: { x: 2, y: 2, z: 2 }, keyLightColor: { red: 0, green: 255, blue: 0 }, keyLightIntensity: 0.9, - stageLatitude: 37.777, - stageLongitude: 122.407, - stageAltitude: 0.03, - stageDay: 60, - stageHour: 12, - stageSunModelEnabled: true + stage: { + latitude: 37.777, + longitude: 122.407, + altitude: 0.03, + day: 60, + hour: 0, + sunModelEnabled: true + } }); print("zoneEntityB:" + zoneEntityB); - var zoneEntityC = Entities.addEntity({ type: "Zone", position: { x: 5, y: 10, z: 5 }, @@ -59,7 +60,6 @@ var zoneEntityC = Entities.addEntity({ print("zoneEntityC:" + zoneEntityC); - // register the call back so it fires before each data send Script.update.connect(function(deltaTime) { // stop it... diff --git a/examples/example/entities/zoneSkyboxExample.js b/examples/example/entities/zoneSkyboxExample.js index a1f5f1917a..420482f14d 100644 --- a/examples/example/entities/zoneSkyboxExample.js +++ b/examples/example/entities/zoneSkyboxExample.js @@ -37,12 +37,14 @@ var zoneEntityA = Entities.addEntity({ color: { red: 255, green: 0, blue: 255 }, url: "" }, - stageLatitude: 37.777, - stageLongitude: 122.407, - stageAltitude: 0.03, - stageDay: 60, - stageHour: 0, - stageSunModelEnabled: true + stage: { + latitude: 37.777, + longitude: 122.407, + altitude: 0.03, + day: 60, + hour: 0, + sunModelEnabled: true + } }); var props = Entities.getEntityProperties(zoneEntityA); diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index bdbfbdf6b6..9cf6a8893f 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -280,6 +280,7 @@ var elZoneStageLatitude = document.getElementById("property-zone-stage-latitude"); var elZoneStageLongitude = document.getElementById("property-zone-stage-longitude"); var elZoneStageAltitude = document.getElementById("property-zone-stage-altitude"); + var elZoneStageAutomaticHourDay = document.getElementById("property-zone-stage-automatic-hour-day"); var elZoneStageDay = document.getElementById("property-zone-stage-day"); var elZoneStageHour = document.getElementById("property-zone-stage-hour"); @@ -480,6 +481,7 @@ elZoneStageLatitude.value = properties.stage.latitude.toFixed(2); elZoneStageLongitude.value = properties.stage.longitude.toFixed(2); elZoneStageAltitude.value = properties.stage.altitude.toFixed(2); + elZoneStageAutomaticHourDay.checked = properties.stage.automaticHourDay; elZoneStageDay.value = properties.stage.day; elZoneStageHour.value = properties.stage.hour; elShapeType.value = properties.shapeType; @@ -636,6 +638,7 @@ elZoneStageLatitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','latitude')); elZoneStageLongitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','longitude')); elZoneStageAltitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','altitude')); + elZoneStageAutomaticHourDay.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('stage','automaticHourDay')); elZoneStageDay.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','day')); elZoneStageHour.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','hour')); @@ -1094,6 +1097,14 @@ + +
+ Stage Automatice Hour Day + + + +
+
Stage Day
diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 79606e687f..943a3824c3 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -426,8 +426,8 @@ void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode, scene->setStageSunModelEnable(_bestZone->getStageProperties().getSunModelEnabled()); scene->setStageLocation(_bestZone->getStageProperties().getLongitude(), _bestZone->getStageProperties().getLatitude(), _bestZone->getStageProperties().getAltitude()); - scene->setStageDayTime(_bestZone->getStageProperties().getHour()); - scene->setStageYearTime(_bestZone->getStageProperties().getDay()); + scene->setStageDayTime(_bestZone->getStageProperties().calculateHour()); + scene->setStageYearTime(_bestZone->getStageProperties().calculateDay()); if (_bestZone->getBackgroundMode() == BACKGROUND_MODE_ATMOSPHERE) { EnvironmentData data = _bestZone->getEnvironmentData(); diff --git a/libraries/entities/src/EntityItemPropertiesMacros.h b/libraries/entities/src/EntityItemPropertiesMacros.h index b93e0e211d..825a98fae0 100644 --- a/libraries/entities/src/EntityItemPropertiesMacros.h +++ b/libraries/entities/src/EntityItemPropertiesMacros.h @@ -302,6 +302,15 @@ } \ } +#define COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT_GETTER(P, S, G) \ + QScriptValue P = object.property(#P); \ + if (P.isValid()) { \ + float newValue = P.toVariant().toFloat(); \ + if (_defaultSettings || newValue != G()) { \ + S(newValue); \ + } \ + } + #define COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(G, P, S) \ { \ QScriptValue G = object.property(#G); \ @@ -339,6 +348,15 @@ } \ } +#define COPY_PROPERTY_FROM_QSCRIPTVALUE_INT_GETTER(P, S, G) \ + QScriptValue P = object.property(#P); \ + if (P.isValid()) { \ + int newValue = P.toVariant().toInt(); \ + if (_defaultSettings || newValue != G()) { \ + S(newValue); \ + } \ + } + #define COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL(P, S) \ QScriptValue P = object.property(#P); \ if (P.isValid()) { \ @@ -348,6 +366,16 @@ } \ } +#define COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL_GETTER(P, S, G) \ + QScriptValue P = object.property(#P); \ + if (P.isValid()) { \ + bool newValue = P.toVariant().toBool(); \ + if (_defaultSettings || newValue != G()) { \ + S(newValue); \ + } \ + } + + #define COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_BOOL(G, P, S) \ { \ QScriptValue G = object.property(#G); \ diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index f40fa67195..93b8c76216 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -146,6 +146,7 @@ enum EntityPropertyList { PROP_BACKGROUND_MODE = PROP_MODEL_URL, PROP_SKYBOX_COLOR = PROP_ANIMATION_URL, PROP_SKYBOX_URL = PROP_ANIMATION_FPS, + PROP_STAGE_AUTOMATIC_HOURDAY = PROP_ANIMATION_FRAME_INDEX, // WARNING!!! DO NOT ADD PROPS_xxx here unless you really really meant to.... Add them UP above }; diff --git a/libraries/entities/src/StagePropertyGroup.cpp b/libraries/entities/src/StagePropertyGroup.cpp index e65a64ba77..80bb763988 100644 --- a/libraries/entities/src/StagePropertyGroup.cpp +++ b/libraries/entities/src/StagePropertyGroup.cpp @@ -9,6 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include +#include +#include + #include #include "StagePropertyGroup.h" @@ -29,6 +33,7 @@ StagePropertyGroup::StagePropertyGroup() { _altitude = DEFAULT_STAGE_ALTITUDE; _day = DEFAULT_STAGE_DAY; _hour = DEFAULT_STAGE_HOUR; + _automaticHourDay = false; } void StagePropertyGroup::copyToScriptValue(QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const { @@ -38,15 +43,26 @@ void StagePropertyGroup::copyToScriptValue(QScriptValue& properties, QScriptEngi COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Stage, stage, Altitude, altitude); COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Stage, stage, Day, day); COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Stage, stage, Hour, hour); + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Stage, stage, AutomaticHourDay, automaticHourDay); } void StagePropertyGroup::copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) { + + // Backward compatibility support for the old way of doing stage properties + COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL_GETTER(stageSunModelEnabled, setSunModelEnabled, getSunModelEnabled); + COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT_GETTER(stageLatitude, setLatitude, getLatitude); + COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT_GETTER(stageLongitude, setLongitude, getLongitude); + COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT_GETTER(stageAltitude, setAltitude, getAltitude); + COPY_PROPERTY_FROM_QSCRIPTVALUE_INT_GETTER(stageDay, setDay, getDay); + COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT_GETTER(stageHour, setHour, getHour); + COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_BOOL(stage, sunModelEnabled, setSunModelEnabled); COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(stage, latitude, setLatitude); COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(stage, longitude, setLongitude); COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(stage, altitude, setAltitude); COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_UINT16(stage, day, setDay); COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(stage, hour, setHour); + COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_BOOL(stage, automaticHourDay, setAutomaticHourDay); } void StagePropertyGroup::debugDump() const { @@ -57,7 +73,7 @@ void StagePropertyGroup::debugDump() const { qDebug() << " _altitude:" << _altitude; qDebug() << " _day:" << _day; qDebug() << " _hour:" << _hour; - + qDebug() << " _automaticHourDay:" << _automaticHourDay; } bool StagePropertyGroup::appentToEditPacket(OctreePacketData* packetData, @@ -75,6 +91,7 @@ bool StagePropertyGroup::appentToEditPacket(OctreePacketData* packetData, APPEND_ENTITY_PROPERTY(PROP_STAGE_ALTITUDE, appendValue, getAltitude()); APPEND_ENTITY_PROPERTY(PROP_STAGE_DAY, appendValue, getDay()); APPEND_ENTITY_PROPERTY(PROP_STAGE_HOUR, appendValue, getHour()); + APPEND_ENTITY_PROPERTY(PROP_STAGE_AUTOMATIC_HOURDAY, appendValue, getAutomaticHourDay()); return true; } @@ -91,6 +108,7 @@ bool StagePropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFlags READ_ENTITY_PROPERTY(PROP_STAGE_ALTITUDE, float, _altitude); READ_ENTITY_PROPERTY(PROP_STAGE_DAY, quint16, _day); READ_ENTITY_PROPERTY(PROP_STAGE_HOUR, float, _hour); + READ_ENTITY_PROPERTY(PROP_STAGE_AUTOMATIC_HOURDAY, bool, _automaticHourDay); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_STAGE_SUN_MODEL_ENABLED, SunModelEnabled); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_STAGE_LATITUDE, Latitude); @@ -98,6 +116,7 @@ bool StagePropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFlags DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_STAGE_ALTITUDE, Altitude); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_STAGE_DAY, Day); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_STAGE_HOUR, Hour); + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_STAGE_AUTOMATIC_HOURDAY, AutomaticHourDay); processedBytes += bytesRead; @@ -111,6 +130,7 @@ void StagePropertyGroup::markAllChanged() { _altitudeChanged = true; _dayChanged = true; _hourChanged = true; + _automaticHourDayChanged = true; } EntityPropertyFlags StagePropertyGroup::getChangedProperties() const { @@ -122,6 +142,7 @@ EntityPropertyFlags StagePropertyGroup::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_STAGE_ALTITUDE, altitude); CHECK_PROPERTY_CHANGE(PROP_STAGE_DAY, day); CHECK_PROPERTY_CHANGE(PROP_STAGE_HOUR, hour); + CHECK_PROPERTY_CHANGE(PROP_STAGE_AUTOMATIC_HOURDAY, automaticHourDay); return changedProperties; } @@ -133,6 +154,7 @@ void StagePropertyGroup::getProperties(EntityItemProperties& properties) const { COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Stage, Altitude, getAltitude); COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Stage, Day, getDay); COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Stage, Hour, getHour); + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Stage, AutomaticHourDay, getAutomaticHourDay); } bool StagePropertyGroup::setProperties(const EntityItemProperties& properties) { @@ -144,6 +166,7 @@ bool StagePropertyGroup::setProperties(const EntityItemProperties& properties) { SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Stage, Altitude, altitude, setAltitude); SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Stage, Day, day, setDay); SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Stage, Hour, hour, setHour); + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Stage, AutomaticHourDay, automaticHourDay, setAutomaticHourDay); return somethingChanged; } @@ -157,6 +180,7 @@ EntityPropertyFlags StagePropertyGroup::getEntityProperties(EncodeBitstreamParam requestedProperties += PROP_STAGE_ALTITUDE; requestedProperties += PROP_STAGE_DAY; requestedProperties += PROP_STAGE_HOUR; + requestedProperties += PROP_STAGE_AUTOMATIC_HOURDAY; return requestedProperties; } @@ -177,7 +201,7 @@ void StagePropertyGroup::appendSubclassData(OctreePacketData* packetData, Encode APPEND_ENTITY_PROPERTY(PROP_STAGE_ALTITUDE, appendValue, getAltitude()); APPEND_ENTITY_PROPERTY(PROP_STAGE_DAY, appendValue, getDay()); APPEND_ENTITY_PROPERTY(PROP_STAGE_HOUR, appendValue, getHour()); - + APPEND_ENTITY_PROPERTY(PROP_STAGE_AUTOMATIC_HOURDAY, appendValue, getAutomaticHourDay()); } int StagePropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, @@ -193,6 +217,41 @@ int StagePropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* da READ_ENTITY_PROPERTY(PROP_STAGE_ALTITUDE, float, _altitude); READ_ENTITY_PROPERTY(PROP_STAGE_DAY, quint16, _day); READ_ENTITY_PROPERTY(PROP_STAGE_HOUR, float, _hour); + READ_ENTITY_PROPERTY(PROP_STAGE_AUTOMATIC_HOURDAY, bool, _automaticHourDay); return bytesRead; } + +static const float TOTAL_LONGITUDES = 360.0f; +static const float HOURS_PER_DAY = 24; +static const float SECONDS_PER_DAY = 60 * 60 * HOURS_PER_DAY; +static const float MSECS_PER_DAY = SECONDS_PER_DAY * MSECS_PER_SECOND; + +float StagePropertyGroup::calculateHour() const { + if (!_automaticHourDay) { + return _hour; + } + + QDateTime utc(QDateTime::currentDateTimeUtc()); + float adjustFromUTC = (_longitude / TOTAL_LONGITUDES); + float offsetFromUTCinMsecs = adjustFromUTC * MSECS_PER_DAY; + int msecsSinceStartOfDay = utc.time().msecsSinceStartOfDay(); + float calutatedHour = ((msecsSinceStartOfDay + offsetFromUTCinMsecs) / MSECS_PER_DAY) * HOURS_PER_DAY; + + // calculate hour based on longitude and time from GMT + return calutatedHour; +} + +uint16_t StagePropertyGroup::calculateDay() const { + + if (!_automaticHourDay) { + return _day; + } + + QDateTime utc(QDateTime::currentDateTimeUtc()); + int calutatedDay = utc.date().dayOfYear(); + + // calculate day based on longitude and time from GMT + return calutatedDay; +} + diff --git a/libraries/entities/src/StagePropertyGroup.h b/libraries/entities/src/StagePropertyGroup.h index 3a1adb1c88..c5df4fe0bd 100644 --- a/libraries/entities/src/StagePropertyGroup.h +++ b/libraries/entities/src/StagePropertyGroup.h @@ -75,6 +75,9 @@ public: static const float DEFAULT_STAGE_ALTITUDE; static const quint16 DEFAULT_STAGE_DAY; static const float DEFAULT_STAGE_HOUR; + + float calculateHour() const; + uint16_t calculateDay() const; DEFINE_PROPERTY(PROP_STAGE_SUN_MODEL_ENABLED, SunModelEnabled, sunModelEnabled, bool); DEFINE_PROPERTY(PROP_STAGE_LATITUDE, Latitude, latitude, float); @@ -82,6 +85,7 @@ public: DEFINE_PROPERTY(PROP_STAGE_ALTITUDE, Altitude, altitude, float); DEFINE_PROPERTY(PROP_STAGE_DAY, Day, day, uint16_t); DEFINE_PROPERTY(PROP_STAGE_HOUR, Hour, hour, float); + DEFINE_PROPERTY(PROP_STAGE_AUTOMATIC_HOURDAY, AutomaticHourDay, automaticHourDay, bool); }; #endif // hifi_StagePropertyGroup_h diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index ec83e18c3d..2fff9c8bb5 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -74,7 +74,7 @@ PacketVersion versionForPacketType(PacketType type) { return 1; case PacketTypeEntityAddOrEdit: case PacketTypeEntityData: - return VERSION_ENTITIES_ZONE_ENTITIES_HAVE_SKYBOX; + return VERSION_ENTITIES_ZONE_ENTITIES_STAGE_HAS_AUTOMATIC_HOURDAY; case PacketTypeEntityErase: return 2; case PacketTypeAudioStreamStats: diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index 38aeed4993..80d32446c8 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -142,5 +142,6 @@ const PacketVersion VERSION_ENTITIES_ZONE_ENTITIES_HAVE_DYNAMIC_SHAPE = 18; const PacketVersion VERSION_ENTITIES_HAVE_NAMES = 19; const PacketVersion VERSION_ENTITIES_ZONE_ENTITIES_HAVE_ATMOSPHERE = 20; const PacketVersion VERSION_ENTITIES_ZONE_ENTITIES_HAVE_SKYBOX = 21; +const PacketVersion VERSION_ENTITIES_ZONE_ENTITIES_STAGE_HAS_AUTOMATIC_HOURDAY = 22; #endif // hifi_PacketHeaders_h From 68e01d2bd9f17f7b26585cc09f9b630d9c8e0d43 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sun, 10 May 2015 17:03:42 -0700 Subject: [PATCH 28/39] quiet compiler --- libraries/gpu/src/gpu/Texture.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 19add9a47e..1cd9d0b29b 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -56,12 +56,12 @@ public: glm::vec4 _borderColor{ 1.0f }; uint32 _maxAnisotropy = 16; + uint8 _filter = FILTER_MIN_MAG_POINT; + uint8 _comparisonFunc = ALWAYS; + uint8 _wrapModeU = WRAP_REPEAT; uint8 _wrapModeV = WRAP_REPEAT; uint8 _wrapModeW = WRAP_REPEAT; - - uint8 _filter = FILTER_MIN_MAG_POINT; - uint8 _comparisonFunc = ALWAYS; uint8 _mipOffset = 0; uint8 _minMip = 0; From e6023c59c18083ebd43a5573aa9fb2cb949f50f6 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sun, 10 May 2015 17:15:48 -0700 Subject: [PATCH 29/39] if _reply is NULL, it doesn't make sense to worry about if it's finished loading or not. --- libraries/networking/src/ResourceCache.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index 54afa98505..c66ae4ce1d 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -241,7 +241,7 @@ float Resource::getLoadPriority() { } void Resource::refresh() { - if (_reply == nullptr && !(_loaded || _failedToLoad)) { + if (_reply && !(_loaded || _failedToLoad)) { return; } if (_reply) { @@ -351,6 +351,7 @@ void Resource::maybeRefresh() { QDateTime lastModifiedOld = metaData.lastModified(); if (lastModified.isValid() && lastModifiedOld.isValid() && lastModifiedOld == lastModified) { + qCDebug(networking) << "Using cached version of" << _url.fileName(); // We don't need to update, return return; } From e51040db5302a2d752d71ed70581a733b250613c Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 11 May 2015 14:31:22 +0200 Subject: [PATCH 30/39] CR --- libraries/render-utils/src/Model.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index db95005a09..080b63370a 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -2068,9 +2068,9 @@ void Model::segregateMeshGroups() { bool hasSpecular = mesh.hasSpecularTexture(); bool hasLightmap = mesh.hasEmissiveTexture(); bool isSkinned = state.clusterMatrices.size() > 1; - bool isWireframe = this->isWireframe(); + bool wireframe = isWireframe(); - if (isWireframe) { + if (wireframe) { translucentMesh = hasTangents = hasSpecular = hasLightmap = isSkinned = false; } @@ -2091,7 +2091,7 @@ void Model::segregateMeshGroups() { qCDebug(renderutils) << "materialID:" << materialID << "parts:" << mesh.parts.size(); } - RenderKey key(translucentMesh, hasLightmap, hasTangents, hasSpecular, isSkinned, isWireframe); + RenderKey key(translucentMesh, hasLightmap, hasTangents, hasSpecular, isSkinned, wireframe); // reuse or create the bucket corresponding to that key and insert the mesh as unsorted _renderBuckets[key.getRaw()]._unsortedMeshes.insertMulti(materialID, i); From 94765f0c531326e8de4ef4242285ca2df39fca40 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 11 May 2015 15:54:14 +0200 Subject: [PATCH 31/39] Add print type --- examples/edit.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/edit.js b/examples/edit.js index 585b45f3f9..64050d92aa 100644 --- a/examples/edit.js +++ b/examples/edit.js @@ -1197,7 +1197,11 @@ PropertiesTool = function(opts) { webView.eventBridge.webEventReceived.connect(function(data) { data = JSON.parse(data); - if (data.type == "update") { + if (data.type == "print") { + if (data.message) { + print(data.message); + } + } else if (data.type == "update") { selectionManager.saveProperties(); if (selectionManager.selections.length > 1) { properties = { From beba293d9683c9a277b5d4c74149892df1f0e03b Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 11 May 2015 15:54:30 +0200 Subject: [PATCH 32/39] Hide Skybox/Atmosphere prps when not needed --- examples/html/entityProperties.html | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index 26bcc63f15..561f39edd2 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -18,6 +18,12 @@ els[i].setAttribute('disabled', 'disabled'); } } + + function showElements(els, show) { + for (var i = 0; i < els.length; i++) { + els[i].style.display = (show) ? 'block' : 'none'; + } + } function createEmitCheckedPropertyUpdateFunction(propertyName) { return function() { @@ -504,6 +510,8 @@ elZoneAtmosphereScatteringWavelengthsZ.value = properties.atmosphere.scatteringWavelengths.z; elZoneAtmosphereHasStars.checked = properties.atmosphere.hasStars; + showElements(document.getElementsByClassName('skybox-section'), elZoneBackgroundMode.value == 'skybox'); + showElements(document.getElementsByClassName('atmosphere-section'), elZoneBackgroundMode.value == 'atmosphere'); } if (selected) { @@ -1117,7 +1125,7 @@
-
+
Skybox Color
R
@@ -1125,13 +1133,13 @@
B
-
+
Skybox URL
-
+
Atmosphere Center
X
@@ -1139,31 +1147,31 @@
Z
-
+
Atmosphere Inner Radius
-
+
Atmosphere Outer Radius
-
+
Atmosphere Mie Scattering
-
+
Atmosphere Rayleigh Scattering
-
+
Atmosphere Scattering Wavelenghts
X
@@ -1171,7 +1179,7 @@
Z
-
+
- Stage Automatice Hour Day + Automatically calculate stage hour and day from location and clock. From aed165809c8b1a2a85e8e4029410183f26b5a3e1 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Mon, 11 May 2015 10:01:49 -0700 Subject: [PATCH 35/39] Use resource cache as long as it is no older than network resource. This allows chache to be used when cdn provides different values for get-vs-head, or for cdn with different resource times in different requests of different sessions. --- libraries/networking/src/ResourceCache.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index c66ae4ce1d..c182b9c1d8 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -350,7 +350,7 @@ void Resource::maybeRefresh() { QDateTime lastModified = variant.value(); QDateTime lastModifiedOld = metaData.lastModified(); if (lastModified.isValid() && lastModifiedOld.isValid() && - lastModifiedOld == lastModified) { + lastModifiedOld >= lastModified) { qCDebug(networking) << "Using cached version of" << _url.fileName(); // We don't need to update, return return; From cdef09c9dd503ab5e330f26c9bb439216bdc0bc7 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Mon, 11 May 2015 10:12:03 -0700 Subject: [PATCH 36/39] Add comment (and force previous change to the right branch). --- libraries/networking/src/ResourceCache.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index c182b9c1d8..0b6e39b151 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -350,7 +350,7 @@ void Resource::maybeRefresh() { QDateTime lastModified = variant.value(); QDateTime lastModifiedOld = metaData.lastModified(); if (lastModified.isValid() && lastModifiedOld.isValid() && - lastModifiedOld >= lastModified) { + lastModifiedOld >= lastModified) { // With >=, cache won't thrash in eventually-consistent cdn. qCDebug(networking) << "Using cached version of" << _url.fileName(); // We don't need to update, return return; From 57f0d9435d6a443caefd94a46c4c90b6dc247039 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Mon, 11 May 2015 10:17:31 -0700 Subject: [PATCH 37/39] Remove change that doesn't belong in this branch. --- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index c10d673890..e4c476c6f7 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -142,7 +142,7 @@ QString EntityTreeRenderer::loadScriptContents(const QString& scriptMaybeURLorTe QUrl url(scriptMaybeURLorText); // If the url is not valid, this must be script text... - if (!url.isValid() || scriptMaybeURLorText.startsWith("(")) { + if (!url.isValid()) { isURL = false; return scriptMaybeURLorText; } From fb9ff6e016e402478ea7a3d4bf0e5a1fb848d90d Mon Sep 17 00:00:00 2001 From: Nex Pro Date: Mon, 11 May 2015 18:50:54 +0100 Subject: [PATCH 38/39] In some cases when the addMenuItem function was called the separator boolean was true by default. This fix addresses this issue by setting it to false. --- libraries/script-engine/src/MenuItemProperties.cpp | 13 ++++++++----- libraries/script-engine/src/MenuItemProperties.h | 4 ++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/libraries/script-engine/src/MenuItemProperties.cpp b/libraries/script-engine/src/MenuItemProperties.cpp index 97fbdef1fa..7015f0abe3 100644 --- a/libraries/script-engine/src/MenuItemProperties.cpp +++ b/libraries/script-engine/src/MenuItemProperties.cpp @@ -23,12 +23,13 @@ MenuItemProperties::MenuItemProperties() : beforeItem(""), afterItem(""), isCheckable(false), - isChecked(false) + isChecked(false), + isSeparator(false) { }; MenuItemProperties::MenuItemProperties(const QString& menuName, const QString& menuItemName, - const QString& shortcutKey, bool checkable, bool checked) : + const QString& shortcutKey, bool checkable, bool checked, bool separator) : menuName(menuName), menuItemName(menuItemName), shortcutKey(shortcutKey), @@ -38,12 +39,13 @@ MenuItemProperties::MenuItemProperties(const QString& menuName, const QString& m beforeItem(""), afterItem(""), isCheckable(checkable), - isChecked(checked) + isChecked(checked), + isSeparator(separator) { } MenuItemProperties::MenuItemProperties(const QString& menuName, const QString& menuItemName, - const KeyEvent& shortcutKeyEvent, bool checkable, bool checked) : + const KeyEvent& shortcutKeyEvent, bool checkable, bool checked, bool separator) : menuName(menuName), menuItemName(menuItemName), shortcutKey(""), @@ -53,7 +55,8 @@ MenuItemProperties::MenuItemProperties(const QString& menuName, const QString& m beforeItem(""), afterItem(""), isCheckable(checkable), - isChecked(checked) + isChecked(checked), + isSeparator(separator) { } diff --git a/libraries/script-engine/src/MenuItemProperties.h b/libraries/script-engine/src/MenuItemProperties.h index 889fb3855a..e58ebe2afb 100644 --- a/libraries/script-engine/src/MenuItemProperties.h +++ b/libraries/script-engine/src/MenuItemProperties.h @@ -22,9 +22,9 @@ class MenuItemProperties { public: MenuItemProperties(); MenuItemProperties(const QString& menuName, const QString& menuItemName, - const QString& shortcutKey = QString(""), bool checkable = false, bool checked = false); + const QString& shortcutKey = QString(""), bool checkable = false, bool checked = false, bool separator = false); MenuItemProperties(const QString& menuName, const QString& menuItemName, - const KeyEvent& shortcutKeyEvent, bool checkable = false, bool checked = false); + const KeyEvent& shortcutKeyEvent, bool checkable = false, bool checked = false, bool separator = false); QString menuName; QString menuItemName; From 51a29bdba60828cf0d44fec50cdd3b169f7ec92c Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Mon, 11 May 2015 11:52:41 -0700 Subject: [PATCH 39/39] Put back the script-fix that belongs in this branch. --- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 943a3824c3..50477356cb 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -142,7 +142,9 @@ QString EntityTreeRenderer::loadScriptContents(const QString& scriptMaybeURLorTe QUrl url(scriptMaybeURLorText); // If the url is not valid, this must be script text... - if (!url.isValid()) { + // We document "direct injection" scripts as starting with "(function...", and that would never be a valid url. + // But QUrl thinks it is. + if (!url.isValid() || scriptMaybeURLorText.startsWith("(")) { isURL = false; return scriptMaybeURLorText; }