From 0e25c85eef01057b884a3d639839197185e4f18a Mon Sep 17 00:00:00 2001 From: Leonardo Murillo Date: Mon, 13 Jan 2014 11:46:27 -0600 Subject: [PATCH 01/29] Trivial change - testing deploy changes --- interface/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 1bbdbde41e..e1dfa8a6c6 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -227,3 +227,4 @@ INSTALL(TARGETS ${TARGET_NAME} BUNDLE DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/install COMPONENT Runtime RUNTIME DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/install COMPONENT Runtime ) + From 3f2c6504a60ff304adc4c454907f450e891a1aeb Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 13 Jan 2014 12:27:47 -0800 Subject: [PATCH 02/29] fix for avatar scale bug, closes #1506 --- interface/src/Application.cpp | 4 ++-- interface/src/avatar/Avatar.cpp | 4 ++-- libraries/avatars/src/AvatarData.cpp | 8 ++++---- libraries/avatars/src/AvatarData.h | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 958995daae..0830f6069f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2128,8 +2128,8 @@ void Application::updateAvatars(float deltaTime, glm::vec3 mouseRayOrigin, glm:: Avatar* avatar = *fade; const float SHRINK_RATE = 0.9f; avatar->setNewScale(avatar->getNewScale() * SHRINK_RATE); - const float MINIMUM_SCALE = 0.001f; - if (avatar->getNewScale() < MINIMUM_SCALE) { + + if (avatar->getNewScale() < MIN_AVATAR_SCALE) { delete avatar; _avatarFades.erase(fade--); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index b3b4793b39..525644b52b 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -439,14 +439,14 @@ void Avatar::goHome() { } void Avatar::increaseSize() { - if ((1.f + SCALING_RATIO) * _newScale < MAX_SCALE) { + if ((1.f + SCALING_RATIO) * _newScale < MAX_AVATAR_SCALE) { _newScale *= (1.f + SCALING_RATIO); qDebug("Changed scale to %f\n", _newScale); } } void Avatar::decreaseSize() { - if (MIN_SCALE < (1.f - SCALING_RATIO) * _newScale) { + if (MIN_AVATAR_SCALE < (1.f - SCALING_RATIO) * _newScale) { _newScale *= (1.f - SCALING_RATIO); qDebug("Changed scale to %f\n", _newScale); } diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 14115ced47..b81a0601bd 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -297,10 +297,10 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) { } void AvatarData::setNewScale(float newScale) { - if (newScale > MAX_SCALE) { - newScale = MAX_SCALE; - } else if (newScale < MIN_SCALE) { - newScale = MIN_SCALE; + if (newScale > MAX_AVATAR_SCALE) { + newScale = MAX_AVATAR_SCALE; + } else if (newScale < MIN_AVATAR_SCALE) { + newScale = MIN_AVATAR_SCALE; } _newScale = newScale; qDebug() << "Changed scale to " << _newScale << "\n"; diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index e7f359aff2..6ee320eae0 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -32,8 +32,8 @@ const int HAND_STATE_START_BIT = 2; // 3rd and 4th bits const int IS_FACESHIFT_CONNECTED = 4; // 5th bit const int IS_CHAT_CIRCLING_ENABLED = 5; -static const float MAX_SCALE = 1000.f; -static const float MIN_SCALE = .005f; +static const float MAX_AVATAR_SCALE = 1000.f; +static const float MIN_AVATAR_SCALE = .005f; const float MAX_AUDIO_LOUDNESS = 1000.0; // close enough for mouth animation @@ -83,7 +83,7 @@ public: // Scale float getNewScale() const { return _newScale; } - void setNewScale(float); + void setNewScale(float newScale); // Hand State void setHandState(char s) { _handState = s; } From 2d5df389071c0af3f2714644ff92dfacd31b5765 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 13 Jan 2014 13:51:51 -0800 Subject: [PATCH 03/29] Persist the user orientation as well as the position, show up a couple meters in front of (and facing) target. Closes #1367. --- interface/src/Application.cpp | 3 ++- interface/src/DataServerClient.cpp | 24 +++++++++++++++++------- interface/src/DataServerClient.h | 1 + interface/src/Menu.cpp | 5 +++-- interface/src/avatar/Profile.cpp | 26 ++++++++++++++++++++++++-- interface/src/avatar/Profile.h | 6 ++++++ 6 files changed, 53 insertions(+), 12 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 958995daae..6e050df72c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1347,8 +1347,9 @@ void Application::timer() { // ask the node list to check in with the domain server NodeList::getInstance()->sendDomainServerCheckIn(); - // give the MyAvatar object position to the Profile so it can propagate to the data-server + // give the MyAvatar object position, orientation to the Profile so it can propagate to the data-server _profile.updatePosition(_myAvatar.getPosition()); + _profile.updateOrientation(_myAvatar.getOrientation()); } static glm::vec3 getFaceVector(BoxFace face) { diff --git a/interface/src/DataServerClient.cpp b/interface/src/DataServerClient.cpp index 33fa59e3e4..56ab92dba3 100644 --- a/interface/src/DataServerClient.cpp +++ b/interface/src/DataServerClient.cpp @@ -175,25 +175,35 @@ void DataServerClient::processSendFromDataServer(unsigned char* packetData, int } } } - } else if (keyList[i] == DataServerKey::Domain && keyList[i + 1] == DataServerKey::Position - && valueList[i] != " " && valueList[i + 1] != " ") { + } else if (keyList[i] == DataServerKey::Domain && keyList[i + 1] == DataServerKey::Position && + keyList[i + 2] == DataServerKey::Orientation && valueList[i] != " " && + valueList[i + 1] != " " && valueList[i + 2] != " ") { QStringList coordinateItems = valueList[i + 1].split(','); + QStringList orientationItems = valueList[i + 2].split(','); - if (coordinateItems.size() == 3) { + if (coordinateItems.size() == 3 && orientationItems.size() == 3) { // send a node kill request, indicating to other clients that they should play the "disappeared" effect NodeList::getInstance()->sendKillNode(&NODE_TYPE_AVATAR_MIXER, 1); qDebug() << "Changing domain to" << valueList[i].toLocal8Bit().constData() << - "and position to" << valueList[i + 1].toLocal8Bit().constData() << + ", position to" << valueList[i + 1].toLocal8Bit().constData() << + ", and orientation to" << valueList[i + 2].toLocal8Bit().constData() << "to go to" << userString << "\n"; NodeList::getInstance()->setDomainHostname(valueList[i]); - glm::vec3 newPosition(coordinateItems[0].toFloat(), - coordinateItems[1].toFloat(), - coordinateItems[2].toFloat()); + // orient the user to face the target + glm::quat newOrientation = glm::quat(glm::radians(glm::vec3(orientationItems[0].toFloat(), + orientationItems[1].toFloat(), orientationItems[2].toFloat()))) * + glm::angleAxis(180.0f, 0.0f, 1.0f, 0.0f); + Application::getInstance()->getAvatar()->setOrientation(newOrientation); + + // move the user a couple units away + const float DISTANCE_TO_USER = 2.0f; + glm::vec3 newPosition = glm::vec3(coordinateItems[0].toFloat(), coordinateItems[1].toFloat(), + coordinateItems[2].toFloat()) - newOrientation * IDENTITY_FRONT * DISTANCE_TO_USER; Application::getInstance()->getAvatar()->setPosition(newPosition); } diff --git a/interface/src/DataServerClient.h b/interface/src/DataServerClient.h index b0ccbe13ee..89ec944eb6 100644 --- a/interface/src/DataServerClient.h +++ b/interface/src/DataServerClient.h @@ -41,6 +41,7 @@ namespace DataServerKey { const QString FaceMeshURL = "mesh"; const QString SkeletonURL = "skeleton"; const QString Position = "position"; + const QString Orientation = "orientation"; const QString UUID = "uuid"; } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 545a765dce..c77be1e0a9 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -999,8 +999,9 @@ void Menu::goToUser() { int dialogReturn = userDialog.exec(); if (dialogReturn == QDialog::Accepted && !userDialog.textValue().isEmpty()) { // there's a username entered by the user, make a request to the data-server - DataServerClient::getValuesForKeysAndUserString((QStringList() << DataServerKey::Domain << DataServerKey::Position), - userDialog.textValue()); + DataServerClient::getValuesForKeysAndUserString( + QStringList() << DataServerKey::Domain << DataServerKey::Position << DataServerKey::Orientation, + userDialog.textValue()); } sendFakeEnterEvent(); diff --git a/interface/src/avatar/Profile.cpp b/interface/src/avatar/Profile.cpp index 4a185f5788..316ca195c9 100644 --- a/interface/src/avatar/Profile.cpp +++ b/interface/src/avatar/Profile.cpp @@ -18,6 +18,7 @@ Profile::Profile(const QString &username) : _uuid(), _lastDomain(), _lastPosition(0.0, 0.0, 0.0), + _lastOrientationSend(0), _faceModelURL() { if (!_username.isEmpty()) { @@ -69,6 +70,10 @@ void Profile::updateDomain(const QString& domain) { } } +static QByteArray createByteArray(const glm::vec3& vector) { + return QByteArray::number(vector.x) + ',' + QByteArray::number(vector.y) + ',' + QByteArray::number(vector.z); +} + void Profile::updatePosition(const glm::vec3 position) { if (_lastPosition != position) { @@ -90,12 +95,29 @@ void Profile::updatePosition(const glm::vec3 position) { gettimeofday(&lastPositionSend, NULL); // send the changed position to the data-server - QString positionString = QString("%1,%2,%3").arg(position.x).arg(position.y).arg(position.z); - DataServerClient::putValueForKey(DataServerKey::Position, positionString.toLocal8Bit().constData()); + DataServerClient::putValueForKey(DataServerKey::Position, createByteArray(position).constData()); } } } +void Profile::updateOrientation(const glm::quat& orientation) { + glm::vec3 eulerAngles = safeEulerAngles(orientation); + if (_lastOrientation == eulerAngles) { + return; + } + const uint64_t DATA_SERVER_ORIENTATION_UPDATE_INTERVAL_USECS = 5 * 1000 * 1000; + const float DATA_SERVER_ORIENTATION_CHANGE_THRESHOLD_DEGREES = 5.0f; + + uint64_t now = usecTimestampNow(); + if (now - _lastOrientationSend >= DATA_SERVER_ORIENTATION_UPDATE_INTERVAL_USECS && + glm::distance(_lastOrientation, eulerAngles) >= DATA_SERVER_ORIENTATION_CHANGE_THRESHOLD_DEGREES) { + DataServerClient::putValueForKey(DataServerKey::Orientation, createByteArray(eulerAngles).constData()); + + _lastOrientation = eulerAngles; + _lastOrientationSend = now; + } +} + void Profile::saveData(QSettings* settings) { settings->beginGroup("Profile"); diff --git a/interface/src/avatar/Profile.h b/interface/src/avatar/Profile.h index eb3f531819..06f8de94a3 100644 --- a/interface/src/avatar/Profile.h +++ b/interface/src/avatar/Profile.h @@ -9,11 +9,14 @@ #ifndef __hifi__Profile__ #define __hifi__Profile__ +#include + #include #include #include #include +#include class Profile { public: @@ -34,6 +37,7 @@ public: void updateDomain(const QString& domain); void updatePosition(const glm::vec3 position); + void updateOrientation(const glm::quat& orientation); QString getLastDomain() const { return _lastDomain; } const glm::vec3& getLastPosition() const { return _lastPosition; } @@ -45,6 +49,8 @@ private: QUuid _uuid; QString _lastDomain; glm::vec3 _lastPosition; + glm::vec3 _lastOrientation; + uint64_t _lastOrientationSend; QUrl _faceModelURL; QUrl _skeletonModelURL; }; From 42e3bcfe9198500cc3eb503e312b56d42fccacd4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 13 Jan 2014 13:52:41 -0800 Subject: [PATCH 04/29] allow fade scale to get smaller than minimum avatar scale --- interface/src/Application.cpp | 9 ++++++--- interface/src/Menu.cpp | 2 +- interface/src/avatar/Avatar.cpp | 26 +++++++++++++------------- interface/src/avatar/MyAvatar.cpp | 12 ++++++------ libraries/avatars/src/AvatarData.cpp | 20 +++++++++----------- libraries/avatars/src/AvatarData.h | 7 ++++--- 6 files changed, 39 insertions(+), 37 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0830f6069f..5d808ff9d4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2127,9 +2127,12 @@ void Application::updateAvatars(float deltaTime, glm::vec3 mouseRayOrigin, glm:: for (vector::iterator fade = _avatarFades.begin(); fade != _avatarFades.end(); fade++) { Avatar* avatar = *fade; const float SHRINK_RATE = 0.9f; - avatar->setNewScale(avatar->getNewScale() * SHRINK_RATE); - - if (avatar->getNewScale() < MIN_AVATAR_SCALE) { + + avatar->setTargetScale(avatar->getScale() * SHRINK_RATE); + + const float MIN_FADE_SCALE = 0.001; + + if (avatar->getTargetScale() < MIN_FADE_SCALE) { delete avatar; _avatarFades.erase(fade--); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 545a765dce..209bc76472 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -891,7 +891,7 @@ void Menu::editPreferences() { _maxVoxelPacketsPerSecond = maxVoxelsPPS->value(); applicationInstance->getAvatar()->setLeanScale(leanScale->value()); - applicationInstance->getAvatar()->setNewScale(avatarScale->value()); + applicationInstance->getAvatar()->setClampedTargetScale(avatarScale->value()); _audioJitterBufferSamples = audioJitterBufferSamples->value(); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 525644b52b..25365dba7a 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -167,8 +167,8 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { follow(NULL); } - if (_scale != _newScale) { - setScale(_newScale); + if (_scale != _targetScale) { + setScale(_targetScale); } // copy velocity so we can use it later for acceleration @@ -439,30 +439,30 @@ void Avatar::goHome() { } void Avatar::increaseSize() { - if ((1.f + SCALING_RATIO) * _newScale < MAX_AVATAR_SCALE) { - _newScale *= (1.f + SCALING_RATIO); - qDebug("Changed scale to %f\n", _newScale); + if ((1.f + SCALING_RATIO) * _targetScale < MAX_AVATAR_SCALE) { + _targetScale *= (1.f + SCALING_RATIO); + qDebug("Changed scale to %f\n", _targetScale); } } void Avatar::decreaseSize() { - if (MIN_AVATAR_SCALE < (1.f - SCALING_RATIO) * _newScale) { - _newScale *= (1.f - SCALING_RATIO); - qDebug("Changed scale to %f\n", _newScale); + if (MIN_AVATAR_SCALE < (1.f - SCALING_RATIO) * _targetScale) { + _targetScale *= (1.f - SCALING_RATIO); + qDebug("Changed scale to %f\n", _targetScale); } } void Avatar::resetSize() { - _newScale = 1.0f; - qDebug("Reseted scale to %f\n", _newScale); + _targetScale = 1.0f; + qDebug("Reseted scale to %f\n", _targetScale); } void Avatar::setScale(const float scale) { _scale = scale; - if (_newScale * (1.f - RESCALING_TOLERANCE) < _scale && - _scale < _newScale * (1.f + RESCALING_TOLERANCE)) { - _scale = _newScale; + if (_targetScale * (1.f - RESCALING_TOLERANCE) < _scale && + _scale < _targetScale * (1.f + RESCALING_TOLERANCE)) { + _scale = _targetScale; } _skeleton.setScale(_scale); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 161ea5b9d8..dabbb7812d 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -92,12 +92,12 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { } // Ajust, scale, position and lookAt position when following an other avatar - if (_leadingAvatar && _newScale != _leadingAvatar->getScale()) { - _newScale = _leadingAvatar->getScale(); + if (_leadingAvatar && _targetScale != _leadingAvatar->getScale()) { + _targetScale = _leadingAvatar->getScale(); } - if (_scale != _newScale) { - float scale = (1.f - SMOOTHING_RATIO) * _scale + SMOOTHING_RATIO * _newScale; + if (_scale != _targetScale) { + float scale = (1.f - SMOOTHING_RATIO) * _scale + SMOOTHING_RATIO * _targetScale; setScale(scale); Application::getInstance()->getCamera()->setScale(scale); } @@ -513,7 +513,7 @@ void MyAvatar::saveData(QSettings* settings) { settings->setValue("pupilDilation", _head.getPupilDilation()); settings->setValue("leanScale", _leanScale); - settings->setValue("scale", _newScale); + settings->setValue("scale", _targetScale); settings->endGroup(); } @@ -536,7 +536,7 @@ void MyAvatar::loadData(QSettings* settings) { _leanScale = loadSetting(settings, "leanScale", 0.05f); - _newScale = loadSetting(settings, "scale", 1.0f); + _targetScale = loadSetting(settings, "scale", 1.0f); setScale(_scale); Application::getInstance()->getCamera()->setScale(_scale); diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index b81a0601bd..f663f26cbf 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -29,7 +29,7 @@ AvatarData::AvatarData(Node* owningNode) : _bodyYaw(-90.0), _bodyPitch(0.0), _bodyRoll(0.0), - _newScale(1.0f), + _targetScale(1.0f), _leaderUUID(), _handState(0), _keyState(NO_KEY_DOWN), @@ -76,7 +76,7 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) { destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _bodyRoll); // Body scale - destinationBuffer += packFloatRatioToTwoByte(destinationBuffer, _newScale); + destinationBuffer += packFloatRatioToTwoByte(destinationBuffer, _targetScale); // Follow mode info memcpy(destinationBuffer, _leaderUUID.toRfc4122().constData(), NUM_BYTES_RFC4122_UUID); @@ -198,7 +198,7 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) { sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*) sourceBuffer, &_bodyRoll); // Body scale - sourceBuffer += unpackFloatRatioFromTwoByte(sourceBuffer, _newScale); + sourceBuffer += unpackFloatRatioFromTwoByte(sourceBuffer, _targetScale); // Follow mode info _leaderUUID = QUuid::fromRfc4122(QByteArray((char*) sourceBuffer, NUM_BYTES_RFC4122_UUID)); @@ -296,12 +296,10 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) { return sourceBuffer - startPosition; } -void AvatarData::setNewScale(float newScale) { - if (newScale > MAX_AVATAR_SCALE) { - newScale = MAX_AVATAR_SCALE; - } else if (newScale < MIN_AVATAR_SCALE) { - newScale = MIN_AVATAR_SCALE; - } - _newScale = newScale; - qDebug() << "Changed scale to " << _newScale << "\n"; +void AvatarData::setClampedTargetScale(float targetScale) { + + targetScale = glm::clamp(targetScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE); + + _targetScale = targetScale; + qDebug() << "Changed scale to " << _targetScale << "\n"; } diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 6ee320eae0..8b46fd8493 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -82,8 +82,9 @@ public: void setBodyRoll(float bodyRoll) { _bodyRoll = bodyRoll; } // Scale - float getNewScale() const { return _newScale; } - void setNewScale(float newScale); + float getTargetScale() const { return _targetScale; } + void setTargetScale(float targetScale) { _targetScale = targetScale; } + void setClampedTargetScale(float targetScale); // Hand State void setHandState(char s) { _handState = s; } @@ -132,7 +133,7 @@ protected: float _bodyRoll; // Body scale - float _newScale; + float _targetScale; // Following mode infos QUuid _leaderUUID; From 9d831a2ab50b8febee6bb8c785152ba09cbaa032 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 13 Jan 2014 14:43:59 -0800 Subject: [PATCH 05/29] Orbit around voxel center, limit hover distance. --- interface/src/Application.cpp | 13 +++++++------ interface/src/Application.h | 2 +- libraries/voxels/src/VoxelTreeElement.h | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6e888d7918..8d758974dd 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1121,7 +1121,7 @@ void Application::mouseMoveEvent(QMouseEvent* event) { return; } if (_isHoverVoxel) { - _myAvatar.orbit(glm::vec3(_hoverVoxel.x, _hoverVoxel.y, _hoverVoxel.z) * (float)TREE_SCALE, deltaX, deltaY); + _myAvatar.orbit(getMouseVoxelWorldCoordinates(_hoverVoxel), deltaX, deltaY); return; } } @@ -1618,10 +1618,9 @@ void Application::makeVoxel(glm::vec3 position, isDestructive); } -const glm::vec3 Application::getMouseVoxelWorldCoordinates(const VoxelDetail _mouseVoxel) { - return glm::vec3((_mouseVoxel.x + _mouseVoxel.s / 2.f) * TREE_SCALE, - (_mouseVoxel.y + _mouseVoxel.s / 2.f) * TREE_SCALE, - (_mouseVoxel.z + _mouseVoxel.s / 2.f) * TREE_SCALE); +glm::vec3 Application::getMouseVoxelWorldCoordinates(const VoxelDetail& mouseVoxel) { + return glm::vec3((mouseVoxel.x + mouseVoxel.s / 2.f) * TREE_SCALE, (mouseVoxel.y + mouseVoxel.s / 2.f) * TREE_SCALE, + (mouseVoxel.z + mouseVoxel.s / 2.f) * TREE_SCALE); } const float NUDGE_PRECISION_MIN = 1 / pow(2.0, 12.0); @@ -2245,7 +2244,9 @@ void Application::updateHoverVoxels(float deltaTime, glm::vec3& mouseRayOrigin, if (!(_voxels.treeIsBusy() || _mousePressed)) { { PerformanceWarning warn(showWarnings, "Application::updateHoverVoxels() _voxels.findRayIntersection()"); - _isHoverVoxel = _voxels.findRayIntersection(mouseRayOrigin, mouseRayDirection, _hoverVoxel, distance, face); + const float MAX_HOVER_DISTANCE = 100.0f; + _isHoverVoxel = _voxels.findRayIntersection(mouseRayOrigin, mouseRayDirection, _hoverVoxel, distance, face) && + glm::distance(getMouseVoxelWorldCoordinates(_hoverVoxel), mouseRayOrigin) < MAX_HOVER_DISTANCE; } if (MAKE_SOUND_ON_VOXEL_HOVER && _isHoverVoxel && glm::vec4(_hoverVoxel.x, _hoverVoxel.y, _hoverVoxel.z, _hoverVoxel.s) != oldVoxel) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 92831ff9ce..1da7de0224 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -142,7 +142,7 @@ public: void removeVoxel(glm::vec3 position, float scale); - const glm::vec3 getMouseVoxelWorldCoordinates(const VoxelDetail _mouseVoxel); + glm::vec3 getMouseVoxelWorldCoordinates(const VoxelDetail& mouseVoxel); QGLWidget* getGLWidget() { return _glWidget; } MyAvatar* getAvatar() { return &_myAvatar; } diff --git a/libraries/voxels/src/VoxelTreeElement.h b/libraries/voxels/src/VoxelTreeElement.h index 1eee7e4a5b..d30007aca1 100644 --- a/libraries/voxels/src/VoxelTreeElement.h +++ b/libraries/voxels/src/VoxelTreeElement.h @@ -92,4 +92,4 @@ protected: }; -#endif /* defined(__hifi__VoxelTreeElement__) */ \ No newline at end of file +#endif /* defined(__hifi__VoxelTreeElement__) */ From f21436a29e7298468408656ee39b2e4a6d933d07 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 13 Jan 2014 15:02:46 -0800 Subject: [PATCH 06/29] Fix (hopefully) for warning on Windows build. --- interface/src/Application.cpp | 4 +--- libraries/metavoxels/src/MetavoxelData.cpp | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8d758974dd..5a6aec5fe8 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2244,9 +2244,7 @@ void Application::updateHoverVoxels(float deltaTime, glm::vec3& mouseRayOrigin, if (!(_voxels.treeIsBusy() || _mousePressed)) { { PerformanceWarning warn(showWarnings, "Application::updateHoverVoxels() _voxels.findRayIntersection()"); - const float MAX_HOVER_DISTANCE = 100.0f; - _isHoverVoxel = _voxels.findRayIntersection(mouseRayOrigin, mouseRayDirection, _hoverVoxel, distance, face) && - glm::distance(getMouseVoxelWorldCoordinates(_hoverVoxel), mouseRayOrigin) < MAX_HOVER_DISTANCE; + _isHoverVoxel = _voxels.findRayIntersection(mouseRayOrigin, mouseRayDirection, _hoverVoxel, distance, face); } if (MAKE_SOUND_ON_VOXEL_HOVER && _isHoverVoxel && glm::vec4(_hoverVoxel.x, _hoverVoxel.y, _hoverVoxel.z, _hoverVoxel.s) != oldVoxel) { diff --git a/libraries/metavoxels/src/MetavoxelData.cpp b/libraries/metavoxels/src/MetavoxelData.cpp index 849d85960e..c04ee9f297 100644 --- a/libraries/metavoxels/src/MetavoxelData.cpp +++ b/libraries/metavoxels/src/MetavoxelData.cpp @@ -301,8 +301,8 @@ void MetavoxelNode::clearChildren(const AttributePointer& attribute) { } int MetavoxelPath::operator[](int index) const { - return _array.at(index * BITS_PER_ELEMENT) | (_array.at(index * BITS_PER_ELEMENT + 1) << 1) | - (_array.at(index * BITS_PER_ELEMENT + 2) << 2); + return (int)_array.at(index * BITS_PER_ELEMENT) | ((int)_array.at(index * BITS_PER_ELEMENT + 1) << 1) | + ((int)_array.at(index * BITS_PER_ELEMENT + 2) << 2); } MetavoxelPath& MetavoxelPath::operator+=(int element) { From 0694a7d4a5ebcde09793ec4be013361ebf788bfd Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 13 Jan 2014 16:09:36 -0800 Subject: [PATCH 07/29] When we fail to download textures or geometry, retry after steadily increasing delays. Closes #1471. --- interface/src/renderer/GeometryCache.cpp | 32 ++++++++++++++++------ interface/src/renderer/GeometryCache.h | 4 +++ interface/src/renderer/TextureCache.cpp | 35 ++++++++++++++++++------ interface/src/renderer/TextureCache.h | 8 ++++-- 4 files changed, 61 insertions(+), 18 deletions(-) diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index 1a32a70c71..7ec61a8942 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -251,18 +251,16 @@ QSharedPointer GeometryCache::getGeometry(const QUrl& url) { } NetworkGeometry::NetworkGeometry(const QUrl& url) : + _modelRequest(url), _modelReply(NULL), - _mappingReply(NULL) + _mappingReply(NULL), + _attempts(0) { if (!url.isValid()) { return; } - QNetworkRequest modelRequest(url); - modelRequest.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); - _modelReply = Application::getInstance()->getNetworkAccessManager()->get(modelRequest); - - connect(_modelReply, SIGNAL(downloadProgress(qint64,qint64)), SLOT(maybeReadModelWithMapping())); - connect(_modelReply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(handleModelReplyError())); + _modelRequest.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); + makeModelRequest(); QUrl mappingURL = url; QString path = url.path(); @@ -312,12 +310,30 @@ glm::vec4 NetworkGeometry::computeAverageColor() const { return (totalTriangles == 0) ? glm::vec4(1.0f, 1.0f, 1.0f, 1.0f) : totalColor / totalTriangles; } +void NetworkGeometry::makeModelRequest() { + _modelReply = Application::getInstance()->getNetworkAccessManager()->get(_modelRequest); + + connect(_modelReply, SIGNAL(downloadProgress(qint64,qint64)), SLOT(maybeReadModelWithMapping())); + connect(_modelReply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(handleModelReplyError())); +} + void NetworkGeometry::handleModelReplyError() { - qDebug() << _modelReply->errorString() << "\n"; + QDebug debug = qDebug() << _modelReply->errorString(); _modelReply->disconnect(this); _modelReply->deleteLater(); _modelReply = NULL; + + // retry with increasing delays + const int MAX_ATTEMPTS = 8; + const int BASE_DELAY_MS = 1000; + if (++_attempts < MAX_ATTEMPTS) { + QTimer::singleShot(BASE_DELAY_MS * (int)pow(2.0, _attempts), this, SLOT(makeModelRequest())); + debug << " -- retrying...\n"; + + } else { + debug << "\n"; + } } void NetworkGeometry::handleMappingReplyError() { diff --git a/interface/src/renderer/GeometryCache.h b/interface/src/renderer/GeometryCache.h index d880d25855..8a68917ba5 100644 --- a/interface/src/renderer/GeometryCache.h +++ b/interface/src/renderer/GeometryCache.h @@ -10,6 +10,7 @@ #define __interface__GeometryCache__ #include +#include #include #include #include @@ -67,15 +68,18 @@ public: private slots: + void makeModelRequest(); void handleModelReplyError(); void handleMappingReplyError(); void maybeReadModelWithMapping(); private: + QNetworkRequest _modelRequest; QNetworkReply* _modelReply; QNetworkReply* _mappingReply; + int _attempts; FBXGeometry _geometry; QVector _meshes; }; diff --git a/interface/src/renderer/TextureCache.cpp b/interface/src/renderer/TextureCache.cpp index 778fb8fb12..6a7d64da5f 100644 --- a/interface/src/renderer/TextureCache.cpp +++ b/interface/src/renderer/TextureCache.cpp @@ -252,16 +252,17 @@ Texture::~Texture() { glDeleteTextures(1, &_id); } -NetworkTexture::NetworkTexture(const QUrl& url, bool normalMap) : _reply(NULL), _averageColor(1.0f, 1.0f, 1.0f, 1.0f) { +NetworkTexture::NetworkTexture(const QUrl& url, bool normalMap) : + _request(url), + _reply(NULL), + _attempts(0), + _averageColor(1.0f, 1.0f, 1.0f, 1.0f) { + if (!url.isValid()) { return; } - QNetworkRequest request(url); - request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); - _reply = Application::getInstance()->getNetworkAccessManager()->get(request); - - connect(_reply, SIGNAL(downloadProgress(qint64,qint64)), SLOT(handleDownloadProgress(qint64,qint64))); - connect(_reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(handleReplyError())); + _request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); + makeRequest(); // default to white/blue glBindTexture(GL_TEXTURE_2D, getID()); @@ -279,6 +280,13 @@ void NetworkTexture::imageLoaded(const QImage& image) { // nothing by default } +void NetworkTexture::makeRequest() { + _reply = Application::getInstance()->getNetworkAccessManager()->get(_request); + + connect(_reply, SIGNAL(downloadProgress(qint64,qint64)), SLOT(handleDownloadProgress(qint64,qint64))); + connect(_reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(handleReplyError())); +} + void NetworkTexture::handleDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) { if (bytesReceived < bytesTotal && !_reply->isFinished()) { return; @@ -314,11 +322,22 @@ void NetworkTexture::handleDownloadProgress(qint64 bytesReceived, qint64 bytesTo } void NetworkTexture::handleReplyError() { - qDebug() << _reply->errorString() << "\n"; + QDebug debug = qDebug() << _reply->errorString(); _reply->disconnect(this); _reply->deleteLater(); _reply = NULL; + + // retry with increasing delays + const int MAX_ATTEMPTS = 8; + const int BASE_DELAY_MS = 1000; + if (++_attempts < MAX_ATTEMPTS) { + QTimer::singleShot(BASE_DELAY_MS * (int)pow(2.0, _attempts), this, SLOT(makeRequest())); + debug << " -- retrying...\n"; + + } else { + debug << "\n"; + } } DilatableNetworkTexture::DilatableNetworkTexture(const QUrl& url, bool normalMap) : diff --git a/interface/src/renderer/TextureCache.h b/interface/src/renderer/TextureCache.h index 40f2bc5ac3..d3f138254f 100644 --- a/interface/src/renderer/TextureCache.h +++ b/interface/src/renderer/TextureCache.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -126,12 +127,15 @@ protected: private slots: + void makeRequest(); void handleDownloadProgress(qint64 bytesReceived, qint64 bytesTotal); void handleReplyError(); - + private: - + + QNetworkRequest _request; QNetworkReply* _reply; + int _attempts; glm::vec4 _averageColor; }; From 7d1a64ca8ce2863669a4c45fa03a1ee32bc88d3a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 13 Jan 2014 17:09:21 -0800 Subject: [PATCH 08/29] change NodeList container to QHash with QSharedPointer --- assignment-client/src/audio/AudioMixer.cpp | 21 +- assignment-client/src/avatars/AvatarMixer.cpp | 18 +- domain-server/src/DomainServer.cpp | 32 +- domain-server/src/DomainServer.h | 6 +- interface/src/Application.cpp | 202 ++++-------- interface/src/Application.h | 10 +- interface/src/Audio.cpp | 4 +- interface/src/DataServerClient.cpp | 11 +- interface/src/MetavoxelSystem.cpp | 13 +- interface/src/MetavoxelSystem.h | 10 +- interface/src/VoxelPacketProcessor.cpp | 5 +- interface/src/VoxelSystem.cpp | 12 +- interface/src/VoxelSystem.h | 8 +- interface/src/avatar/Avatar.cpp | 21 -- interface/src/avatar/Avatar.h | 2 - interface/src/avatar/Hand.cpp | 25 +- interface/src/avatar/MyAvatar.cpp | 71 +---- interface/src/avatar/MyAvatar.h | 1 - interface/src/ui/VoxelStatsDialog.cpp | 95 +++--- libraries/audio/src/AudioInjector.cpp | 4 +- libraries/avatars/src/AvatarData.cpp | 9 - libraries/avatars/src/AvatarData.h | 5 - .../src/OctreeInboundPacketProcessor.cpp | 6 +- .../octree-server/src/OctreeSendThread.cpp | 4 +- libraries/octree-server/src/OctreeServer.cpp | 15 +- libraries/octree-server/src/OctreeServer.h | 10 +- libraries/octree/src/JurisdictionListener.cpp | 24 +- libraries/octree/src/JurisdictionListener.h | 12 +- libraries/octree/src/JurisdictionSender.cpp | 4 +- libraries/octree/src/JurisdictionSender.h | 1 + .../octree/src/OctreeEditPacketSender.cpp | 43 +-- .../particles/src/ParticleCollisionSystem.cpp | 14 +- libraries/shared/src/NodeList.cpp | 299 +++++------------- libraries/shared/src/NodeList.h | 73 +---- .../shared/src/ReceivedPacketProcessor.cpp | 2 +- 35 files changed, 355 insertions(+), 737 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index e315d366f8..d15f7172ae 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -182,15 +182,13 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf } void AudioMixer::prepareMixForListeningNode(Node* node) { - NodeList* nodeList = NodeList::getInstance(); - AvatarAudioRingBuffer* nodeRingBuffer = ((AudioMixerClientData*) node->getLinkedData())->getAvatarAudioRingBuffer(); // zero out the client mix for this node memset(_clientSamples, 0, sizeof(_clientSamples)); // loop through all other nodes that have sufficient audio to mix - for (NodeList::iterator otherNode = nodeList->begin(); otherNode != nodeList->end(); otherNode++) { + foreach(SharedNodePointer otherNode, NodeList::getInstance()->getNodeHash()) { if (otherNode->getLinkedData()) { AudioMixerClientData* otherNodeClientData = (AudioMixerClientData*) otherNode->getLinkedData(); @@ -200,7 +198,7 @@ void AudioMixer::prepareMixForListeningNode(Node* node) { PositionalAudioRingBuffer* otherNodeBuffer = otherNodeClientData->getRingBuffers()[i]; if ((*otherNode != *node - || otherNodeBuffer->shouldLoopbackForNode()) + || otherNodeBuffer->shouldLoopbackForNode()) && otherNodeBuffer->willBeAddedToMix()) { addBufferToMixForListeningNodeWithBuffer(otherNodeBuffer, nodeRingBuffer); } @@ -220,10 +218,10 @@ void AudioMixer::processDatagram(const QByteArray& dataByteArray, const HifiSock NodeList* nodeList = NodeList::getInstance(); - Node* matchingNode = nodeList->nodeWithUUID(nodeUUID); + SharedNodePointer matchingNode = nodeList->nodeWithUUID(nodeUUID); if (matchingNode) { - nodeList->updateNodeWithData(matchingNode, senderSockAddr, (unsigned char*) dataByteArray.data(), dataByteArray.size()); + nodeList->updateNodeWithData(matchingNode.data(), senderSockAddr, (unsigned char*) dataByteArray.data(), dataByteArray.size()); if (!matchingNode->getActiveSocket()) { // we don't have an active socket for this node, but they're talking to us @@ -264,14 +262,14 @@ void AudioMixer::run() { if (_isFinished) { break; } - - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + + foreach(SharedNodePointer node, nodeList->getNodeHash()) { if (node->getLinkedData()) { ((AudioMixerClientData*) node->getLinkedData())->checkBuffersBeforeFrameSend(JITTER_BUFFER_SAMPLES); } } - - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + + foreach(SharedNodePointer node, nodeList->getNodeHash()) { if (node->getType() == NODE_TYPE_AGENT && node->getActiveSocket() && node->getLinkedData() && ((AudioMixerClientData*) node->getLinkedData())->getAvatarAudioRingBuffer()) { prepareMixForListeningNode(&(*node)); @@ -284,12 +282,13 @@ void AudioMixer::run() { } // push forward the next output pointers for any audio buffers we used - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + foreach(SharedNodePointer node, nodeList->getNodeHash()) { if (node->getLinkedData()) { ((AudioMixerClientData*) node->getLinkedData())->pushBuffersAfterFrameSend(); } } + int usecToSleep = usecTimestamp(&startTime) + (++nextFrame * BUFFER_SEND_INTERVAL_USECS) - usecTimestampNow(); if (usecToSleep > 0) { diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index f6096fd18a..b614e7ac2b 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -67,7 +67,7 @@ void broadcastAvatarData() { NodeList* nodeList = NodeList::getInstance(); - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + foreach(SharedNodePointer node, nodeList->getNodeHash()) { if (node->getLinkedData() && node->getType() == NODE_TYPE_AGENT && node->getActiveSocket()) { // reset packet pointers for this node @@ -76,7 +76,7 @@ void broadcastAvatarData() { // this is an AGENT we have received head data from // send back a packet with other active node data to this node - for (NodeList::iterator otherNode = nodeList->begin(); otherNode != nodeList->end(); otherNode++) { + foreach(SharedNodePointer otherNode, nodeList->getNodeHash()) { if (otherNode->getLinkedData() && otherNode->getUUID() != node->getUUID()) { unsigned char* avatarDataEndpoint = addNodeToBroadcastPacket((unsigned char*)&avatarDataBuffer[0], @@ -109,13 +109,11 @@ void broadcastAvatarData() { packetsSent++; //printf("packetsSent=%d packetLength=%d\n", packetsSent, packetLength); - NodeList::getInstance()->getNodeSocket().writeDatagram((char*) broadcastPacket, currentBufferPosition - broadcastPacket, - node->getActiveSocket()->getAddress(), - node->getActiveSocket()->getPort()); + nodeList->getNodeSocket().writeDatagram((char*) broadcastPacket, currentBufferPosition - broadcastPacket, + node->getActiveSocket()->getAddress(), + node->getActiveSocket()->getPort()); } } - - } void AvatarMixer::processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr) { @@ -128,11 +126,11 @@ void AvatarMixer::processDatagram(const QByteArray& dataByteArray, const HifiSoc NUM_BYTES_RFC4122_UUID)); // add or update the node in our list - Node* avatarNode = nodeList->nodeWithUUID(nodeUUID); + SharedNodePointer avatarNode = nodeList->nodeWithUUID(nodeUUID); if (avatarNode) { // parse positional data from an node - nodeList->updateNodeWithData(avatarNode, senderSockAddr, + nodeList->updateNodeWithData(avatarNode.data(), senderSockAddr, (unsigned char*) dataByteArray.data(), dataByteArray.size()); } else { break; @@ -144,7 +142,7 @@ void AvatarMixer::processDatagram(const QByteArray& dataByteArray, const HifiSoc QUuid nodeUUID = QUuid::fromRfc4122(dataByteArray.mid(numBytesForPacketHeader((unsigned char*) dataByteArray.data()), NUM_BYTES_RFC4122_UUID)); // let everyone else know about the update - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + foreach(SharedNodePointer node, nodeList->getNodeHash()) { if (node->getActiveSocket() && node->getUUID() != nodeUUID) { nodeList->getNodeSocket().writeDatagram(dataByteArray, node->getActiveSocket()->getAddress(), diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index ec1875668a..4d47aa3885 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -77,7 +77,7 @@ DomainServer::DomainServer(int argc, char* argv[]) : // Start the web server. mg_start(&callbacks, NULL, options); - nodeList->addHook(this); + connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), SLOT(nodeKilled(SharedNodePointer))); if (!_staticAssignmentFile.exists() || _voxelServerConfig) { @@ -171,10 +171,10 @@ void DomainServer::readAvailableDatagrams() { nodeLocalAddress, nodeUUID))) { - Node* checkInNode = nodeList->addOrUpdateNode(nodeUUID, - nodeType, - nodePublicAddress, - nodeLocalAddress); + SharedNodePointer checkInNode = nodeList->addOrUpdateNode(nodeUUID, + nodeType, + nodePublicAddress, + nodeLocalAddress); if (matchingStaticAssignment) { // this was a newly added node with a matching static assignment @@ -201,7 +201,7 @@ void DomainServer::readAvailableDatagrams() { if (numInterestTypes > 0) { // if the node has sent no types of interest, assume they want nothing but their own ID back - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + foreach(SharedNodePointer node, nodeList->getNodeHash()) { if (node->getUUID() != nodeUUID && memchr(nodeTypesOfInterest, node->getType(), numInterestTypes)) { @@ -318,9 +318,7 @@ int DomainServer::civetwebRequestHandler(struct mg_connection *connection) { QJsonObject assignedNodesJSON; // enumerate the NodeList to find the assigned nodes - NodeList* nodeList = NodeList::getInstance(); - - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) { if (node->getLinkedData()) { // add the node using the UUID as the key QString uuidString = uuidStringWithoutCurlyBraces(node->getUUID()); @@ -372,10 +370,10 @@ int DomainServer::civetwebRequestHandler(struct mg_connection *connection) { // enumerate the NodeList to find the assigned nodes NodeList* nodeList = NodeList::getInstance(); - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + foreach(SharedNodePointer node, nodeList->getNodeHash()) { // add the node using the UUID as the key QString uuidString = uuidStringWithoutCurlyBraces(node->getUUID()); - nodesJSON[uuidString] = jsonObjectForNode(&(*node)); + nodesJSON[uuidString] = jsonObjectForNode(node.data()); } rootJSON["nodes"] = nodesJSON; @@ -410,14 +408,14 @@ int DomainServer::civetwebRequestHandler(struct mg_connection *connection) { QUuid deleteUUID = QUuid(QString(ri->uri + strlen(URI_NODE) + sizeof('/'))); if (!deleteUUID.isNull()) { - Node *nodeToKill = NodeList::getInstance()->nodeWithUUID(deleteUUID); + SharedNodePointer nodeToKill = NodeList::getInstance()->nodeWithUUID(deleteUUID); if (nodeToKill) { // start with a 200 response mg_printf(connection, "%s", RESPONSE_200); // we have a valid UUID and node - kill the node that has this assignment - NodeList::getInstance()->killNode(nodeToKill); + NodeList::getInstance()->killNodeWithUUID(deleteUUID); // successfully processed request return 1; @@ -494,10 +492,6 @@ void DomainServer::addReleasedAssignmentBackToQueue(Assignment* releasedAssignme } } -void DomainServer::nodeAdded(Node* node) { - -} - void DomainServer::nodeKilled(Node* node) { // if this node has linked data it was from an assignment if (node->getLinkedData()) { @@ -741,7 +735,7 @@ bool DomainServer::checkInWithUUIDMatchesExistingNode(const HifiSockAddr& nodePu const QUuid& checkInUUID) { NodeList* nodeList = NodeList::getInstance(); - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + foreach(SharedNodePointer node, nodeList->getNodeHash()) { if (node->getLinkedData() && nodePublicSocket == node->getPublicSocket() && nodeLocalSocket == node->getLocalSocket() @@ -773,7 +767,7 @@ void DomainServer::addStaticAssignmentsBackToQueueAfterRestart() { NodeList* nodeList = NodeList::getInstance(); // enumerate the nodes and check if there is one with an attached assignment with matching UUID - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + foreach(SharedNodePointer node, nodeList->getNodeHash()) { if (node->getLinkedData()) { Assignment* linkedAssignment = (Assignment*) node->getLinkedData(); if (linkedAssignment->getUUID() == _staticAssignments[i].getUUID()) { diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 10cb58b786..99bd560228 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -22,7 +22,7 @@ const int MAX_STATIC_ASSIGNMENT_FILE_ASSIGNMENTS = 1000; -class DomainServer : public QCoreApplication, public NodeListHook { +class DomainServer : public QCoreApplication { Q_OBJECT public: DomainServer(int argc, char* argv[]); @@ -31,10 +31,10 @@ public: static void setDomainServerInstance(DomainServer* domainServer); - /// Called by NodeList to inform us that a node has been added. - void nodeAdded(Node* node); +public slots: /// Called by NodeList to inform us that a node has been killed. void nodeKilled(Node* node); + private: static int civetwebRequestHandler(struct mg_connection *connection); static void civetwebUploadHandler(struct mg_connection *connection, const char *path); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 958995daae..e28114034b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -173,9 +173,11 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : connect(audioThread, SIGNAL(started()), &_audio, SLOT(start())); audioThread->start(); - - nodeList->addHook(&_voxels); - nodeList->addHook(this); + + connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), SLOT(nodeKilled(SharedNodePointer))); + connect(nodeList, SIGNAL(nodeAdded(SharedNodePointer)), &_voxels, SLOT(nodeAdded(SharedNodePointer))); + connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), &_voxels, SLOT(nodeKilled(SharedNodePointer))); + nodeList->addDomainListener(this); // network receive thread and voxel parsing thread are both controlled by the --nonblocking command line @@ -263,8 +265,6 @@ Application::~Application() { _audio.thread()->wait(); storeSizeAndPosition(); - NodeList::getInstance()->removeHook(&_voxels); - NodeList::getInstance()->removeHook(this); NodeList::getInstance()->removeDomainListener(this); _sharedVoxelSystem.changeTree(new VoxelTree); @@ -1441,7 +1441,7 @@ void Application::terminate() { static Avatar* processAvatarMessageHeader(unsigned char*& packetData, size_t& dataBytes) { // record the packet for stats-tracking Application::getInstance()->getBandwidthMeter()->inputStream(BandwidthMeter::AVATARS).updateValue(dataBytes); - Node* avatarMixerNode = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_AVATAR_MIXER); + SharedNodePointer avatarMixerNode = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_AVATAR_MIXER); if (avatarMixerNode) { avatarMixerNode->recordBytesReceived(dataBytes); } @@ -1458,7 +1458,7 @@ static Avatar* processAvatarMessageHeader(unsigned char*& packetData, size_t& da dataBytes -= NUM_BYTES_RFC4122_UUID; // make sure the node exists - Node* node = NodeList::getInstance()->nodeWithUUID(nodeUUID); + SharedNodePointer node = NodeList::getInstance()->nodeWithUUID(nodeUUID); if (!node || !node->getLinkedData()) { return NULL; } @@ -1985,16 +1985,16 @@ void Application::updateLookatTargetAvatar(const glm::vec3& mouseRayOrigin, cons Avatar* Application::findLookatTargetAvatar(const glm::vec3& mouseRayOrigin, const glm::vec3& mouseRayDirection, glm::vec3& eyePosition, QUuid& nodeUUID = DEFAULT_NODE_ID_REF) { - NodeList* nodeList = NodeList::getInstance(); - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) { if (node->getLinkedData() != NULL && node->getType() == NODE_TYPE_AGENT) { Avatar* avatar = (Avatar*)node->getLinkedData(); float distance; + if (avatar->findRayIntersection(mouseRayOrigin, mouseRayDirection, distance)) { // rescale to compensate for head embiggening eyePosition = (avatar->getHead().calculateAverageEyePosition() - avatar->getHead().getScalePivot()) * - (avatar->getScale() / avatar->getHead().getScale()) + avatar->getHead().getScalePivot(); - + (avatar->getScale() / avatar->getHead().getScale()) + avatar->getHead().getScalePivot(); + _lookatIndicatorScale = avatar->getHead().getScale(); _lookatOtherPosition = avatar->getHead().getPosition(); nodeUUID = avatar->getOwningNode()->getUUID(); @@ -2002,6 +2002,7 @@ Avatar* Application::findLookatTargetAvatar(const glm::vec3& mouseRayOrigin, con } } } + return NULL; } @@ -2026,71 +2027,6 @@ void Application::renderLookatIndicator(glm::vec3 pointOfInterest) { renderCircle(haloOrigin, INDICATOR_RADIUS, IDENTITY_UP, NUM_SEGMENTS); } -void maybeBeginFollowIndicator(bool& began) { - if (!began) { - Application::getInstance()->getGlowEffect()->begin(); - glLineWidth(5); - glBegin(GL_LINES); - began = true; - } -} - -void Application::renderFollowIndicator() { - NodeList* nodeList = NodeList::getInstance(); - - // initialize lazily so that we don't enable the glow effect unnecessarily - bool began = false; - - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); ++node) { - if (node->getLinkedData() != NULL && node->getType() == NODE_TYPE_AGENT) { - Avatar* avatar = (Avatar *) node->getLinkedData(); - Avatar* leader = NULL; - - if (!avatar->getLeaderUUID().isNull()) { - if (avatar->getLeaderUUID() == NodeList::getInstance()->getOwnerUUID()) { - leader = &_myAvatar; - } else { - for (NodeList::iterator it = nodeList->begin(); it != nodeList->end(); ++it) { - if(it->getUUID() == avatar->getLeaderUUID() - && it->getType() == NODE_TYPE_AGENT) { - leader = (Avatar*) it->getLinkedData(); - } - } - } - - if (leader != NULL) { - maybeBeginFollowIndicator(began); - glColor3f(1.f, 0.f, 0.f); - glVertex3f((avatar->getHead().getPosition().x + avatar->getPosition().x) / 2.f, - (avatar->getHead().getPosition().y + avatar->getPosition().y) / 2.f, - (avatar->getHead().getPosition().z + avatar->getPosition().z) / 2.f); - glColor3f(0.f, 1.f, 0.f); - glVertex3f((leader->getHead().getPosition().x + leader->getPosition().x) / 2.f, - (leader->getHead().getPosition().y + leader->getPosition().y) / 2.f, - (leader->getHead().getPosition().z + leader->getPosition().z) / 2.f); - } - } - } - } - - if (_myAvatar.getLeadingAvatar() != NULL) { - maybeBeginFollowIndicator(began); - glColor3f(1.f, 0.f, 0.f); - glVertex3f((_myAvatar.getHead().getPosition().x + _myAvatar.getPosition().x) / 2.f, - (_myAvatar.getHead().getPosition().y + _myAvatar.getPosition().y) / 2.f, - (_myAvatar.getHead().getPosition().z + _myAvatar.getPosition().z) / 2.f); - glColor3f(0.f, 1.f, 0.f); - glVertex3f((_myAvatar.getLeadingAvatar()->getHead().getPosition().x + _myAvatar.getLeadingAvatar()->getPosition().x) / 2.f, - (_myAvatar.getLeadingAvatar()->getHead().getPosition().y + _myAvatar.getLeadingAvatar()->getPosition().y) / 2.f, - (_myAvatar.getLeadingAvatar()->getHead().getPosition().z + _myAvatar.getLeadingAvatar()->getPosition().z) / 2.f); - } - - if (began) { - glEnd(); - _glowEffect.end(); - } -} - void Application::renderHighlightVoxel(VoxelDetail voxel) { glDisable(GL_LIGHTING); glPushMatrix(); @@ -2108,9 +2044,8 @@ void Application::renderHighlightVoxel(VoxelDetail voxel) { void Application::updateAvatars(float deltaTime, glm::vec3 mouseRayOrigin, glm::vec3 mouseRayDirection) { bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::updateAvatars()"); - NodeList* nodeList = NodeList::getInstance(); - - for(NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + + foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) { node->lock(); if (node->getLinkedData()) { Avatar *avatar = (Avatar *)node->getLinkedData(); @@ -2739,39 +2674,36 @@ void Application::queryOctree(NODE_TYPE serverType, PACKET_TYPE packetType, Node unsigned char voxelQueryPacket[MAX_PACKET_SIZE]; - NodeList* nodeList = NodeList::getInstance(); - // Iterate all of the nodes, and get a count of how many voxel servers we have... int totalServers = 0; int inViewServers = 0; int unknownJurisdictionServers = 0; - - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { - + + foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) { // only send to the NodeTypes that are serverType if (node->getActiveSocket() != NULL && node->getType() == serverType) { totalServers++; - + // get the server bounds for this server QUuid nodeUUID = node->getUUID(); - + // if we haven't heard from this voxel server, go ahead and send it a query, so we // can get the jurisdiction... if (jurisdictions.find(nodeUUID) == jurisdictions.end()) { unknownJurisdictionServers++; } else { const JurisdictionMap& map = (jurisdictions)[nodeUUID]; - + unsigned char* rootCode = map.getRootOctalCode(); - + if (rootCode) { VoxelPositionSize rootDetails; voxelDetailsForCode(rootCode, rootDetails); AABox serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s); serverBounds.scale(TREE_SCALE); - + ViewFrustum::location serverFrustumLocation = _viewFrustum.boxInFrustum(serverBounds); - + if (serverFrustumLocation != ViewFrustum::OUTSIDE) { inViewServers++; } @@ -2804,18 +2736,20 @@ void Application::queryOctree(NODE_TYPE serverType, PACKET_TYPE packetType, Node if (wantExtraDebugging && unknownJurisdictionServers > 0) { qDebug("perServerPPS: %d perUnknownServer: %d\n", perServerPPS, perUnknownServer); } - - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + + NodeList* nodeList = NodeList::getInstance(); + + foreach(SharedNodePointer node, nodeList->getNodeHash()) { // only send to the NodeTypes that are serverType if (node->getActiveSocket() != NULL && node->getType() == serverType) { - - + + // get the server bounds for this server QUuid nodeUUID = node->getUUID(); - + bool inView = false; bool unknownView = false; - + // if we haven't heard from this voxel server, go ahead and send it a query, so we // can get the jurisdiction... if (jurisdictions.find(nodeUUID) == jurisdictions.end()) { @@ -2825,15 +2759,15 @@ void Application::queryOctree(NODE_TYPE serverType, PACKET_TYPE packetType, Node } } else { const JurisdictionMap& map = (jurisdictions)[nodeUUID]; - + unsigned char* rootCode = map.getRootOctalCode(); - + if (rootCode) { VoxelPositionSize rootDetails; voxelDetailsForCode(rootCode, rootDetails); AABox serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s); serverBounds.scale(TREE_SCALE); - + ViewFrustum::location serverFrustumLocation = _viewFrustum.boxInFrustum(serverBounds); if (serverFrustumLocation != ViewFrustum::OUTSIDE) { inView = true; @@ -2846,15 +2780,15 @@ void Application::queryOctree(NODE_TYPE serverType, PACKET_TYPE packetType, Node } } } - + if (inView) { _voxelQuery.setMaxOctreePacketsPerSecond(perServerPPS); } else if (unknownView) { if (wantExtraDebugging) { qDebug() << "no known jurisdiction for node " << *node << ", give it budget of " - << perUnknownServer << " to send us jurisdiction.\n"; + << perUnknownServer << " to send us jurisdiction.\n"; } - + // set the query's position/orientation to be degenerate in a manner that will get the scene quickly // If there's only one server, then don't do this, and just let the normal voxel query pass through // as expected... this way, we will actually get a valid scene if there is one to be seen @@ -2878,24 +2812,24 @@ void Application::queryOctree(NODE_TYPE serverType, PACKET_TYPE packetType, Node } // set up the packet for sending... unsigned char* endOfVoxelQueryPacket = voxelQueryPacket; - + // insert packet type/version and node UUID endOfVoxelQueryPacket += populateTypeAndVersion(endOfVoxelQueryPacket, packetType); QByteArray ownerUUID = nodeList->getOwnerUUID().toRfc4122(); memcpy(endOfVoxelQueryPacket, ownerUUID.constData(), ownerUUID.size()); endOfVoxelQueryPacket += ownerUUID.size(); - + // encode the query data... endOfVoxelQueryPacket += _voxelQuery.getBroadcastData(endOfVoxelQueryPacket); - + int packetLength = endOfVoxelQueryPacket - voxelQueryPacket; - + // make sure we still have an active socket if (node->getActiveSocket()) { nodeList->getNodeSocket().writeDatagram((char*) voxelQueryPacket, packetLength, - node->getActiveSocket()->getAddress(), node->getActiveSocket()->getPort()); + node->getActiveSocket()->getAddress(), node->getActiveSocket()->getPort()); } - + // Feed number of bytes to corresponding channel of the bandwidth meter _bandwidthMeter.outputStream(BandwidthMeter::VOXELS).updateValue(packetLength); } @@ -3252,12 +3186,6 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { } } - { - PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), - "Application::displaySide() ... renderFollowIndicator..."); - renderFollowIndicator(); - } - // render transmitter pick ray, if non-empty if (_transmitterPickStart != _transmitterPickEnd) { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), @@ -3384,12 +3312,12 @@ void Application::displayOverlay() { glPointSize(1.0f); char nodes[100]; - NodeList* nodeList = NodeList::getInstance(); int totalAvatars = 0, totalServers = 0; - - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + + foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) { node->getType() == NODE_TYPE_AGENT ? totalAvatars++ : totalServers++; } + sprintf(nodes, "Servers: %d, Avatars: %d\n", totalServers, totalAvatars); drawtext(_glWidget->width() - 150, 20, 0.10, 0, 1.0, 0, nodes, 1, 0, 0); } @@ -3489,8 +3417,8 @@ void Application::displayStats() { int pingAudio = 0, pingAvatar = 0, pingVoxel = 0, pingVoxelMax = 0; NodeList* nodeList = NodeList::getInstance(); - Node* audioMixerNode = nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER); - Node* avatarMixerNode = nodeList->soloNodeOfType(NODE_TYPE_AVATAR_MIXER); + SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER); + SharedNodePointer avatarMixerNode = nodeList->soloNodeOfType(NODE_TYPE_AVATAR_MIXER); pingAudio = audioMixerNode ? audioMixerNode->getPingMs() : 0; pingAvatar = avatarMixerNode ? avatarMixerNode->getPingMs() : 0; @@ -3499,7 +3427,8 @@ void Application::displayStats() { // Now handle voxel servers, since there could be more than one, we average their ping times unsigned long totalPingVoxel = 0; int voxelServerCount = 0; - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + + foreach(SharedNodePointer node, nodeList->getNodeHash()) { if (node->getType() == NODE_TYPE_VOXEL_SERVER) { totalPingVoxel += node->getPingMs(); voxelServerCount++; @@ -3508,6 +3437,7 @@ void Application::displayStats() { } } } + if (voxelServerCount) { pingVoxel = totalPingVoxel/voxelServerCount; } @@ -3524,7 +3454,7 @@ void Application::displayStats() { sprintf(avatarStats, "Avatar: pos %.3f, %.3f, %.3f, vel %.1f, yaw = %.2f", avatarPos.x, avatarPos.y, avatarPos.z, glm::length(_myAvatar.getVelocity()), _myAvatar.getBodyYaw()); drawtext(10, statsVerticalOffset, 0.10f, 0, 1.0, 0, avatarStats); - Node* avatarMixer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_AVATAR_MIXER); + SharedNodePointer avatarMixer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_AVATAR_MIXER); char avatarMixerStats[200]; if (avatarMixer) { sprintf(avatarMixerStats, "Avatar Mixer: %.f kbps, %.f pps", @@ -3848,10 +3778,10 @@ void Application::renderAvatars(bool forceRenderHead, bool selfAvatarOnly) { if (!selfAvatarOnly) { // Render avatars of other nodes NodeList* nodeList = NodeList::getInstance(); - - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + + foreach(SharedNodePointer node, nodeList->getNodeHash()) { node->lock(); - + if (node->getLinkedData() != NULL && node->getType() == NODE_TYPE_AGENT) { Avatar *avatar = (Avatar *)node->getLinkedData(); if (!avatar->isInitialized()) { @@ -3860,7 +3790,7 @@ void Application::renderAvatars(bool forceRenderHead, bool selfAvatarOnly) { avatar->render(false); avatar->setDisplayingLookatVectors(Menu::getInstance()->isOptionChecked(MenuOption::LookAtVectors)); } - + node->unlock(); } @@ -4106,18 +4036,6 @@ void Application::eyedropperVoxelUnderCursor() { } } -void Application::toggleFollowMode() { - glm::vec3 mouseRayOrigin, mouseRayDirection; - _viewFrustum.computePickRay(_pieMenu.getX() / (float)_glWidget->width(), - _pieMenu.getY() / (float)_glWidget->height(), - mouseRayOrigin, mouseRayDirection); - glm::vec3 eyePositionIgnored; - QUuid nodeUUIDIgnored; - Avatar* leadingAvatar = findLookatTargetAvatar(mouseRayOrigin, mouseRayDirection, eyePositionIgnored, nodeUUIDIgnored); - - _myAvatar.follow(leadingAvatar); -} - void Application::resetSensors() { _headMouseX = _mouseX = _glWidget->width() / 2; _headMouseY = _mouseY = _glWidget->height() / 2; @@ -4200,11 +4118,7 @@ void Application::domainChanged(QString domain) { updateLocalOctreeCache(); } -void Application::nodeAdded(Node* node) { - -} - -void Application::nodeKilled(Node* node) { +void Application::nodeKilled(SharedNodePointer node) { if (node->getType() == NODE_TYPE_VOXEL_SERVER) { QUuid nodeUUID = node->getUUID(); // see if this is the first we've heard of this node... @@ -4284,7 +4198,7 @@ void Application::trackIncomingVoxelPacket(unsigned char* messageData, ssize_t m const HifiSockAddr& senderSockAddr, bool wasStatsPacket) { // Attempt to identify the sender from it's address. - Node* serverNode = NodeList::getInstance()->nodeWithAddress(senderSockAddr); + SharedNodePointer serverNode = NodeList::getInstance()->nodeWithAddress(senderSockAddr); if (serverNode) { QUuid nodeUUID = serverNode->getUUID(); @@ -4301,7 +4215,7 @@ void Application::trackIncomingVoxelPacket(unsigned char* messageData, ssize_t m int Application::parseOctreeStats(unsigned char* messageData, ssize_t messageLength, const HifiSockAddr& senderSockAddr) { // But, also identify the sender, and keep track of the contained jurisdiction root for this server - Node* server = NodeList::getInstance()->nodeWithAddress(senderSockAddr); + SharedNodePointer server = NodeList::getInstance()->nodeWithAddress(senderSockAddr); // parse the incoming stats datas stick it in a temporary object for now, while we // determine which server it belongs to diff --git a/interface/src/Application.h b/interface/src/Application.h index 92831ff9ce..a0bf608e98 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -95,7 +95,7 @@ static const float NODE_KILLED_RED = 1.0f; static const float NODE_KILLED_GREEN = 0.0f; static const float NODE_KILLED_BLUE = 0.0f; -class Application : public QApplication, public NodeListHook, public PacketSenderNotify, public DomainChangeListener { +class Application : public QApplication, public PacketSenderNotify, public DomainChangeListener { Q_OBJECT friend class VoxelPacketProcessor; @@ -194,8 +194,7 @@ public: void computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& near, float& far, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const; - virtual void nodeAdded(Node* node); - virtual void nodeKilled(Node* node); + virtual void packetSentNotification(ssize_t length); virtual void domainChanged(QString domain); @@ -214,6 +213,8 @@ public: void setIsHighlightVoxel(bool isHighlightVoxel) { _isHighlightVoxel = isHighlightVoxel; } public slots: + void nodeKilled(SharedNodePointer node); + void sendAvatarFaceVideoMessage(int frameCount, const QByteArray& data); void exportVoxels(); void importVoxels(); @@ -250,8 +251,6 @@ private slots: glm::vec2 getScaledScreenPoint(glm::vec2 projectedPoint); - void toggleFollowMode(); - void closeMirrorView(); void restoreMirrorView(); void shrinkMirrorView(); @@ -301,7 +300,6 @@ private: bool isLookingAtMyAvatar(Avatar* avatar); void renderLookatIndicator(glm::vec3 pointOfInterest); - void renderFollowIndicator(); void renderHighlightVoxel(VoxelDetail voxel); void updateAvatar(float deltaTime); diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 429b0ec66a..9349223691 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -365,9 +365,9 @@ void Audio::handleAudioInput() { NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL); NodeList* nodeList = NodeList::getInstance(); - Node* audioMixer = nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER); + SharedNodePointer audioMixer = nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER); - if (audioMixer && nodeList->getNodeActiveSocketOrPing(audioMixer)) { + if (audioMixer && nodeList->getNodeActiveSocketOrPing(audioMixer.data())) { MyAvatar* interfaceAvatar = Application::getInstance()->getAvatar(); glm::vec3 headPosition = interfaceAvatar->getHeadJointPosition(); diff --git a/interface/src/DataServerClient.cpp b/interface/src/DataServerClient.cpp index 33fa59e3e4..34fe0b165c 100644 --- a/interface/src/DataServerClient.cpp +++ b/interface/src/DataServerClient.cpp @@ -144,14 +144,14 @@ void DataServerClient::processSendFromDataServer(unsigned char* packetData, int Application::getInstance()->getProfile()->setFaceModelURL(QUrl(valueList[i])); } else { // mesh URL for a UUID, find avatar in our list - NodeList* nodeList = NodeList::getInstance(); - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + + foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) { if (node->getLinkedData() != NULL && node->getType() == NODE_TYPE_AGENT) { Avatar* avatar = (Avatar *) node->getLinkedData(); if (avatar->getUUID() == userUUID) { QMetaObject::invokeMethod(&avatar->getHead().getFaceModel(), - "setURL", Q_ARG(QUrl, QUrl(valueList[i]))); + "setURL", Q_ARG(QUrl, QUrl(valueList[i]))); } } } @@ -163,14 +163,13 @@ void DataServerClient::processSendFromDataServer(unsigned char* packetData, int Application::getInstance()->getProfile()->setSkeletonModelURL(QUrl(valueList[i])); } else { // skeleton URL for a UUID, find avatar in our list - NodeList* nodeList = NodeList::getInstance(); - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) { if (node->getLinkedData() != NULL && node->getType() == NODE_TYPE_AGENT) { Avatar* avatar = (Avatar *) node->getLinkedData(); if (avatar->getUUID() == userUUID) { QMetaObject::invokeMethod(&avatar->getSkeletonModel(), "setURL", - Q_ARG(QUrl, QUrl(valueList[i]))); + Q_ARG(QUrl, QUrl(valueList[i]))); } } } diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 355b027e93..fc72f7444e 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -26,10 +26,6 @@ MetavoxelSystem::MetavoxelSystem() : _buffer(QOpenGLBuffer::VertexBuffer) { } -MetavoxelSystem::~MetavoxelSystem() { - NodeList::getInstance()->removeHook(this); -} - void MetavoxelSystem::init() { if (!_program.isLinked()) { switchToResourcesParentIfRequired(); @@ -39,7 +35,10 @@ void MetavoxelSystem::init() { _pointScaleLocation = _program.uniformLocation("pointScale"); } - NodeList::getInstance()->addHook(this); + NodeList* nodeList = NodeList::getInstance(); + + connect(nodeList, SIGNAL(nodeAdded(SharedNodePointer)), SLOT(nodeAdded(SharedNodePointer))); + connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), SLOT(nodeKilled(SharedNodePointer))); AttributeRegistry::getInstance()->configureScriptEngine(&_scriptEngine); @@ -117,14 +116,14 @@ void MetavoxelSystem::render() { _program.release(); } -void MetavoxelSystem::nodeAdded(Node* node) { +void MetavoxelSystem::nodeAdded(SharedNodePointer node) { if (node->getType() == NODE_TYPE_METAVOXEL_SERVER) { QMetaObject::invokeMethod(this, "addClient", Q_ARG(const QUuid&, node->getUUID()), Q_ARG(const HifiSockAddr&, node->getLocalSocket())); } } -void MetavoxelSystem::nodeKilled(Node* node) { +void MetavoxelSystem::nodeKilled(SharedNodePointer node) { if (node->getType() == NODE_TYPE_METAVOXEL_SERVER) { QMetaObject::invokeMethod(this, "removeClient", Q_ARG(const QUuid&, node->getUUID())); } diff --git a/interface/src/MetavoxelSystem.h b/interface/src/MetavoxelSystem.h index ddb69644d5..a58729285d 100644 --- a/interface/src/MetavoxelSystem.h +++ b/interface/src/MetavoxelSystem.h @@ -26,13 +26,11 @@ class MetavoxelClient; /// Renders a metavoxel tree. -class MetavoxelSystem : public QObject, public NodeListHook { +class MetavoxelSystem : public QObject { Q_OBJECT public: - MetavoxelSystem(); - ~MetavoxelSystem(); void init(); @@ -41,9 +39,9 @@ public: void simulate(float deltaTime); void render(); - virtual void nodeAdded(Node* node); - virtual void nodeKilled(Node* node); - +public slots: + void nodeAdded(SharedNodePointer node); + void nodeKilled(SharedNodePointer node); private: Q_INVOKABLE void addClient(const QUuid& uuid, const HifiSockAddr& address); diff --git a/interface/src/VoxelPacketProcessor.cpp b/interface/src/VoxelPacketProcessor.cpp index 6e5d4ca85c..76b2ce55fc 100644 --- a/interface/src/VoxelPacketProcessor.cpp +++ b/interface/src/VoxelPacketProcessor.cpp @@ -57,12 +57,13 @@ void VoxelPacketProcessor::processPacket(const HifiSockAddr& senderSockAddr, uns if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) { app->trackIncomingVoxelPacket(packetData, messageLength, senderSockAddr, wasStatsPacket); - Node* serverNode = NodeList::getInstance()->nodeWithAddress(senderSockAddr); + SharedNodePointer serverNode = NodeList::getInstance()->nodeWithAddress(senderSockAddr); if (serverNode && serverNode->getActiveSocket() && *serverNode->getActiveSocket() == senderSockAddr) { switch(packetData[0]) { case PACKET_TYPE_PARTICLE_DATA: { - app->_particles.processDatagram(QByteArray((char*) packetData, messageLength), senderSockAddr, serverNode); + app->_particles.processDatagram(QByteArray((char*) packetData, messageLength), + senderSockAddr, serverNode.data()); } break; case PACKET_TYPE_ENVIRONMENT_DATA: { diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index ede9a8e15d..7dfa4158cf 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -1604,13 +1604,13 @@ void VoxelSystem::falseColorizeBySource() { }; // create a bunch of colors we'll use during colorization - NodeList* nodeList = NodeList::getInstance(); - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + + foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) { if (node->getType() == NODE_TYPE_VOXEL_SERVER) { uint16_t nodeID = VoxelTreeElement::getSourceNodeUUIDKey(node->getUUID()); int groupColor = voxelServerCount % NUMBER_OF_COLOR_GROUPS; args.colors[nodeID] = groupColors[groupColor]; - + if (groupColors[groupColor].red > 0) { groupColors[groupColor].red = ((groupColors[groupColor].red - MIN_COLOR)/2) + MIN_COLOR; } @@ -1620,7 +1620,7 @@ void VoxelSystem::falseColorizeBySource() { if (groupColors[groupColor].blue > 0) { groupColors[groupColor].blue = ((groupColors[groupColor].blue - MIN_COLOR)/2) + MIN_COLOR; } - + voxelServerCount++; } } @@ -2683,7 +2683,7 @@ void VoxelSystem::falseColorizeOccludedV2() { setupNewVoxelsForDrawing(); } -void VoxelSystem::nodeAdded(Node* node) { +void VoxelSystem::nodeAdded(SharedNodePointer node) { if (node->getType() == NODE_TYPE_VOXEL_SERVER) { qDebug("VoxelSystem... voxel server %s added...\n", node->getUUID().toString().toLocal8Bit().constData()); _voxelServerCount++; @@ -2704,7 +2704,7 @@ bool VoxelSystem::killSourceVoxelsOperation(OctreeElement* element, void* extraD return true; } -void VoxelSystem::nodeKilled(Node* node) { +void VoxelSystem::nodeKilled(SharedNodePointer node) { if (node->getType() == NODE_TYPE_VOXEL_SERVER) { _voxelServerCount--; QUuid nodeUUID = node->getUUID(); diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index e9f0cc47ab..a1bce77be1 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -37,8 +37,7 @@ struct VoxelShaderVBOData }; -class VoxelSystem : public NodeData, public OctreeElementDeleteHook, public OctreeElementUpdateHook, - public NodeListHook { +class VoxelSystem : public NodeData, public OctreeElementDeleteHook, public OctreeElementUpdateHook { Q_OBJECT friend class VoxelHideShowThread; @@ -112,8 +111,6 @@ public: virtual void elementDeleted(OctreeElement* element); virtual void elementUpdated(OctreeElement* element); - virtual void nodeAdded(Node* node); - virtual void nodeKilled(Node* node); bool treeIsBusy() const { return _treeIsBusy; } @@ -124,6 +121,9 @@ signals: void importProgress(int progress); public slots: + void nodeAdded(SharedNodePointer node); + void nodeKilled(SharedNodePointer node); + void collectStatsForTreesAndVBOs(); // Methods that recurse tree diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index b3b4793b39..9bc77b1f5d 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -95,7 +95,6 @@ Avatar::Avatar(Node* owningNode) : _mouseRayOrigin(0.0f, 0.0f, 0.0f), _mouseRayDirection(0.0f, 0.0f, 0.0f), _isCollisionsOn(true), - _leadingAvatar(NULL), _moving(false), _initialized(false), _handHoldingPosition(0.0f, 0.0f, 0.0f), @@ -146,27 +145,7 @@ glm::quat Avatar::getWorldAlignedOrientation () const { return computeRotationFromBodyToWorldUp() * getOrientation(); } -void Avatar::follow(Avatar* leadingAvatar) { - const float MAX_STRING_LENGTH = 2; - - _leadingAvatar = leadingAvatar; - if (_leadingAvatar != NULL) { - _leaderUUID = leadingAvatar->getOwningNode()->getUUID(); - _stringLength = glm::length(_position - _leadingAvatar->getPosition()) / _scale; - if (_stringLength > MAX_STRING_LENGTH) { - _stringLength = MAX_STRING_LENGTH; - } - } else { - _leaderUUID = QUuid(); - } -} - void Avatar::simulate(float deltaTime, Transmitter* transmitter) { - - if (_leadingAvatar && !_leadingAvatar->getOwningNode()->isAlive()) { - follow(NULL); - } - if (_scale != _newScale) { setScale(_newScale); } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 1a4511275a..6fa9528741 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -135,7 +135,6 @@ public: void init(); void simulate(float deltaTime, Transmitter* transmitter); - void follow(Avatar* leadingAvatar); void render(bool forceRenderHead); //setters @@ -217,7 +216,6 @@ protected: glm::vec3 _mouseRayOrigin; glm::vec3 _mouseRayDirection; bool _isCollisionsOn; - Avatar* _leadingAvatar; float _stringLength; bool _moving; ///< set when position is changing diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 2cbbd6fa51..78be4a1864 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -368,8 +368,7 @@ void Hand::updateCollisions() { glm::vec3 totalPenetration; // check other avatars - NodeList* nodeList = NodeList::getInstance(); - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) { if (node->getLinkedData() && node->getType() == NODE_TYPE_AGENT) { Avatar* otherAvatar = (Avatar*)node->getLinkedData(); if (Menu::getInstance()->isOptionChecked(MenuOption::PlaySlaps)) { @@ -388,21 +387,21 @@ void Hand::updateCollisions() { if (glm::length(otherPalmPosition - myPalmPosition) < palmCollisionDistance) { palm.setIsCollidingWithPalm(true); if (!wasColliding) { - const float PALM_COLLIDE_VOLUME = 1.f; - const float PALM_COLLIDE_FREQUENCY = 1000.f; - const float PALM_COLLIDE_DURATION_MAX = 0.75f; - const float PALM_COLLIDE_DECAY_PER_SAMPLE = 0.01f; - Application::getInstance()->getAudio()->startDrumSound(PALM_COLLIDE_VOLUME, - PALM_COLLIDE_FREQUENCY, - PALM_COLLIDE_DURATION_MAX, - PALM_COLLIDE_DECAY_PER_SAMPLE); - // If the other person's palm is in motion, move mine downward to show I was hit - const float MIN_VELOCITY_FOR_SLAP = 0.05f; + const float PALM_COLLIDE_VOLUME = 1.f; + const float PALM_COLLIDE_FREQUENCY = 1000.f; + const float PALM_COLLIDE_DURATION_MAX = 0.75f; + const float PALM_COLLIDE_DECAY_PER_SAMPLE = 0.01f; + Application::getInstance()->getAudio()->startDrumSound(PALM_COLLIDE_VOLUME, + PALM_COLLIDE_FREQUENCY, + PALM_COLLIDE_DURATION_MAX, + PALM_COLLIDE_DECAY_PER_SAMPLE); + // If the other person's palm is in motion, move mine downward to show I was hit + const float MIN_VELOCITY_FOR_SLAP = 0.05f; if (glm::length(otherPalm.getVelocity()) > MIN_VELOCITY_FOR_SLAP) { // add slapback here } } - + } } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 161ea5b9d8..1e6b2565ce 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -87,15 +87,6 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { _elapsedTimeMoving += deltaTime; } - if (_leadingAvatar && !_leadingAvatar->getOwningNode()->isAlive()) { - follow(NULL); - } - - // Ajust, scale, position and lookAt position when following an other avatar - if (_leadingAvatar && _newScale != _leadingAvatar->getScale()) { - _newScale = _leadingAvatar->getScale(); - } - if (_scale != _newScale) { float scale = (1.f - SMOOTHING_RATIO) * _scale + SMOOTHING_RATIO * _newScale; setScale(scale); @@ -327,9 +318,7 @@ void MyAvatar::updateFromGyrosAndOrWebcam(bool turnWithHead) { estimatedRotation = webcam->getEstimatedRotation(); } else { - if (!_leadingAvatar) { - _head.setPitch(_head.getMousePitch()); - } + _head.setPitch(_head.getMousePitch()); _head.getVideoFace().clearFrame(); // restore rotation, lean to neutral positions @@ -634,47 +623,6 @@ void MyAvatar::updateThrust(float deltaTime, Transmitter * transmitter) { _shouldJump = false; } - - // Add thrusts from leading avatar - const float FOLLOWING_RATE = 0.02f; - const float MIN_YAW = 5.0f; - const float MIN_PITCH = 1.0f; - const float PITCH_RATE = 0.1f; - const float MIN_YAW_BEFORE_PITCH = 30.0f; - - if (_leadingAvatar != NULL) { - glm::vec3 toTarget = _leadingAvatar->getPosition() - _position; - - if (glm::length(_position - _leadingAvatar->getPosition()) > _scale * _stringLength) { - _position += toTarget * FOLLOWING_RATE; - } else { - toTarget = _leadingAvatar->getHead().getLookAtPosition() - _head.getPosition(); - } - toTarget = glm::vec3(glm::dot(right, toTarget), - glm::dot(up , toTarget), - glm::dot(front, toTarget)); - - float yawAngle = angleBetween(-IDENTITY_FRONT, glm::vec3(toTarget.x, 0.f, toTarget.z)); - if (glm::abs(yawAngle) > MIN_YAW){ - if (IDENTITY_RIGHT.x * toTarget.x + IDENTITY_RIGHT.y * toTarget.y + IDENTITY_RIGHT.z * toTarget.z > 0) { - _bodyYawDelta -= yawAngle; - } else { - _bodyYawDelta += yawAngle; - } - } - - float pitchAngle = glm::abs(90.0f - angleBetween(IDENTITY_UP, toTarget)); - if (glm::abs(pitchAngle) > MIN_PITCH && yawAngle < MIN_YAW_BEFORE_PITCH){ - if (IDENTITY_UP.x * toTarget.x + IDENTITY_UP.y * toTarget.y + IDENTITY_UP.z * toTarget.z > 0) { - _head.setMousePitch(_head.getMousePitch() + PITCH_RATE * pitchAngle); - } else { - _head.setMousePitch(_head.getMousePitch() - PITCH_RATE * pitchAngle); - } - _head.setPitch(_head.getMousePitch()); - } - } - - // Add thrusts from Transmitter if (transmitter) { transmitter->checkForLostTransmitter(); @@ -873,15 +821,7 @@ void MyAvatar::updateAvatarCollisions(float deltaTime) { // Reset detector for nearest avatar _distanceToNearestAvatar = std::numeric_limits::max(); - // loop through all the other avatars for potential interactions... - NodeList* nodeList = NodeList::getInstance(); - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { - if (node->getLinkedData() && node->getType() == NODE_TYPE_AGENT) { - //Avatar *otherAvatar = (Avatar *)node->getLinkedData(); - // - // Placeholder: Add code here when we want to add Avatar<->Avatar collision stuff - } - } + // loop through all the other avatars for potential interactions } class SortedAvatar { @@ -902,10 +842,10 @@ void MyAvatar::updateChatCircle(float deltaTime) { // find all circle-enabled members and sort by distance QVector sortedAvatars; - NodeList* nodeList = NodeList::getInstance(); - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + + foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) { if (node->getLinkedData() && node->getType() == NODE_TYPE_AGENT) { - SortedAvatar sortedAvatar; + SortedAvatar sortedAvatar; sortedAvatar.avatar = (Avatar*)node->getLinkedData(); if (!sortedAvatar.avatar->isChatCirclingEnabled()) { continue; @@ -914,6 +854,7 @@ void MyAvatar::updateChatCircle(float deltaTime) { sortedAvatars.append(sortedAvatar); } } + qSort(sortedAvatars.begin(), sortedAvatars.end()); // compute the accumulated centers diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 99cc360d59..474c212623 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -51,7 +51,6 @@ public: float getAbsoluteHeadYaw() const; const glm::vec3& getMouseRayOrigin() const { return _mouseRayOrigin; } const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; } - Avatar* getLeadingAvatar() const { return _leadingAvatar; } glm::vec3 getGravity() const { return _gravity; } glm::vec3 getUprightHeadPosition() const; glm::vec3 getEyeLevelPosition() const; diff --git a/interface/src/ui/VoxelStatsDialog.cpp b/interface/src/ui/VoxelStatsDialog.cpp index 3a2c8468ad..a25fe9f097 100644 --- a/interface/src/ui/VoxelStatsDialog.cpp +++ b/interface/src/ui/VoxelStatsDialog.cpp @@ -241,9 +241,10 @@ void VoxelStatsDialog::showOctreeServersOfType(int& serverCount, NODE_TYPE serve NodeToJurisdictionMap& serverJurisdictions) { QLocale locale(QLocale::English); - + NodeList* nodeList = NodeList::getInstance(); - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + + foreach(SharedNodePointer node, nodeList->getNodeHash()) { // only send to the NodeTypes that are NODE_TYPE_VOXEL_SERVER if (node->getType() == serverType) { serverCount++; @@ -261,7 +262,7 @@ void VoxelStatsDialog::showOctreeServersOfType(int& serverCount, NODE_TYPE serve std::stringstream serverDetails(""); std::stringstream extraDetails(""); std::stringstream linkDetails(""); - + if (nodeList->getNodeActiveSocketOrPing(&(*node))) { serverDetails << "active "; } else { @@ -270,29 +271,29 @@ void VoxelStatsDialog::showOctreeServersOfType(int& serverCount, NODE_TYPE serve QUuid nodeUUID = node->getUUID(); - // lookup our nodeUUID in the jurisdiction map, if it's missing then we're + // lookup our nodeUUID in the jurisdiction map, if it's missing then we're // missing at least one jurisdiction if (serverJurisdictions.find(nodeUUID) == serverJurisdictions.end()) { serverDetails << " unknown jurisdiction "; } else { const JurisdictionMap& map = serverJurisdictions[nodeUUID]; - + unsigned char* rootCode = map.getRootOctalCode(); - + if (rootCode) { QString rootCodeHex = octalCodeToHexString(rootCode); - + VoxelPositionSize rootDetails; voxelDetailsForCode(rootCode, rootDetails); AABox serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s); serverBounds.scale(TREE_SCALE); - serverDetails << " jurisdiction: " - << rootCodeHex.toLocal8Bit().constData() - << " [" - << rootDetails.x << ", " - << rootDetails.y << ", " - << rootDetails.z << ": " - << rootDetails.s << "] "; + serverDetails << " jurisdiction: " + << rootCodeHex.toLocal8Bit().constData() + << " [" + << rootDetails.x << ", " + << rootDetails.y << ", " + << rootDetails.z << ": " + << rootDetails.s << "] "; } else { serverDetails << " jurisdiction has no rootCode"; } // root code @@ -304,7 +305,7 @@ void VoxelStatsDialog::showOctreeServersOfType(int& serverCount, NODE_TYPE serve NodeToVoxelSceneStats* sceneStats = Application::getInstance()->getOcteeSceneStats(); if (sceneStats->find(nodeUUID) != sceneStats->end()) { VoxelSceneStats& stats = sceneStats->at(nodeUUID); - + switch (_extraServerDetails[serverCount-1]) { case MOST: { extraDetails << "
" ; @@ -312,14 +313,14 @@ void VoxelStatsDialog::showOctreeServersOfType(int& serverCount, NODE_TYPE serve const unsigned long USECS_PER_MSEC = 1000; float lastFullEncode = stats.getLastFullTotalEncodeTime() / USECS_PER_MSEC; float lastFullSend = stats.getLastFullElapsedTime() / USECS_PER_MSEC; - + QString lastFullEncodeString = locale.toString(lastFullEncode); QString lastFullSendString = locale.toString(lastFullSend); - - extraDetails << "
" << "Last Full Scene... " << - "Encode Time: " << lastFullEncodeString.toLocal8Bit().constData() << " ms " << - "Send Time: " << lastFullSendString.toLocal8Bit().constData() << " ms "; - + + extraDetails << "
" << "Last Full Scene... " << + "Encode Time: " << lastFullEncodeString.toLocal8Bit().constData() << " ms " << + "Send Time: " << lastFullSendString.toLocal8Bit().constData() << " ms "; + for (int i = 0; i < VoxelSceneStats::ITEM_COUNT; i++) { VoxelSceneStats::Item item = (VoxelSceneStats::Item)(i); VoxelSceneStats::ItemInfo& itemInfo = stats.getItemInfo(item); @@ -330,44 +331,44 @@ void VoxelStatsDialog::showOctreeServersOfType(int& serverCount, NODE_TYPE serve QString totalString = locale.toString((uint)stats.getTotalElements()); QString internalString = locale.toString((uint)stats.getTotalInternal()); QString leavesString = locale.toString((uint)stats.getTotalLeaves()); - + serverDetails << "
" << "Node UUID: " << - nodeUUID.toString().toLocal8Bit().constData() << " "; - + nodeUUID.toString().toLocal8Bit().constData() << " "; + serverDetails << "
" << "Voxels: " << - totalString.toLocal8Bit().constData() << " total " << - internalString.toLocal8Bit().constData() << " internal " << - leavesString.toLocal8Bit().constData() << " leaves "; - + totalString.toLocal8Bit().constData() << " total " << + internalString.toLocal8Bit().constData() << " internal " << + leavesString.toLocal8Bit().constData() << " leaves "; + QString incomingPacketsString = locale.toString((uint)stats.getIncomingPackets()); QString incomingBytesString = locale.toString((uint)stats.getIncomingBytes()); QString incomingWastedBytesString = locale.toString((uint)stats.getIncomingWastedBytes()); QString incomingOutOfOrderString = locale.toString((uint)stats.getIncomingOutOfOrder()); QString incomingLikelyLostString = locale.toString((uint)stats.getIncomingLikelyLost()); - + int clockSkewInMS = node->getClockSkewUsec() / (int)USECS_PER_MSEC; QString incomingFlightTimeString = locale.toString((int)stats.getIncomingFlightTimeAverage()); QString incomingPingTimeString = locale.toString(node->getPingMs()); QString incomingClockSkewString = locale.toString(clockSkewInMS); - + serverDetails << "
" << "Incoming Packets: " << - incomingPacketsString.toLocal8Bit().constData() << - " Out of Order: " << incomingOutOfOrderString.toLocal8Bit().constData() << - " Likely Lost: " << incomingLikelyLostString.toLocal8Bit().constData(); - + incomingPacketsString.toLocal8Bit().constData() << + " Out of Order: " << incomingOutOfOrderString.toLocal8Bit().constData() << + " Likely Lost: " << incomingLikelyLostString.toLocal8Bit().constData(); + serverDetails << "
" << - " Average Flight Time: " << incomingFlightTimeString.toLocal8Bit().constData() << " msecs"; - - serverDetails << "
" << - " Average Ping Time: " << incomingPingTimeString.toLocal8Bit().constData() << " msecs"; - - serverDetails << "
" << - " Average Clock Skew: " << incomingClockSkewString.toLocal8Bit().constData() << " msecs"; - + " Average Flight Time: " << incomingFlightTimeString.toLocal8Bit().constData() << " msecs"; + + serverDetails << "
" << + " Average Ping Time: " << incomingPingTimeString.toLocal8Bit().constData() << " msecs"; + + serverDetails << "
" << + " Average Clock Skew: " << incomingClockSkewString.toLocal8Bit().constData() << " msecs"; + serverDetails << "
" << "Incoming" << - " Bytes: " << incomingBytesString.toLocal8Bit().constData() << - " Wasted Bytes: " << incomingWastedBytesString.toLocal8Bit().constData(); - + " Bytes: " << incomingBytesString.toLocal8Bit().constData() << + " Wasted Bytes: " << incomingWastedBytesString.toLocal8Bit().constData(); + serverDetails << extraDetails.str(); if (_extraServerDetails[serverCount-1] == MORE) { linkDetails << " " << " [most...]"; @@ -376,7 +377,7 @@ void VoxelStatsDialog::showOctreeServersOfType(int& serverCount, NODE_TYPE serve linkDetails << " " << " [less...]"; linkDetails << " " << " [least...]"; } - + } break; case LESS: { // nothing @@ -391,7 +392,7 @@ void VoxelStatsDialog::showOctreeServersOfType(int& serverCount, NODE_TYPE serve serverDetails << linkDetails.str(); _labels[_voxelServerLables[serverCount - 1]]->setText(serverDetails.str().c_str()); } // is VOXEL_SERVER - } // Node Loop + } } void VoxelStatsDialog::reject() { diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 722c2a6dbd..60ff777452 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -103,9 +103,9 @@ void AudioInjector::injectAudio() { // grab our audio mixer from the NodeList, if it exists - Node* audioMixer = nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER); + SharedNodePointer audioMixer = nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER); - if (audioMixer && nodeList->getNodeActiveSocketOrPing(audioMixer)) { + if (audioMixer && nodeList->getNodeActiveSocketOrPing(audioMixer.data())) { // send off this audio packet nodeList->getNodeSocket().writeDatagram((char*) injectedAudioPacket, (currentPacketPosition - injectedAudioPacket) + bytesToCopy, diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 14115ced47..8ba5f6e984 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -30,7 +30,6 @@ AvatarData::AvatarData(Node* owningNode) : _bodyPitch(0.0), _bodyRoll(0.0), _newScale(1.0f), - _leaderUUID(), _handState(0), _keyState(NO_KEY_DOWN), _isChatCirclingEnabled(false), @@ -77,10 +76,6 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) { // Body scale destinationBuffer += packFloatRatioToTwoByte(destinationBuffer, _newScale); - - // Follow mode info - memcpy(destinationBuffer, _leaderUUID.toRfc4122().constData(), NUM_BYTES_RFC4122_UUID); - destinationBuffer += NUM_BYTES_RFC4122_UUID; // Head rotation (NOTE: This needs to become a quaternion to save two bytes) destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headData->_yaw); @@ -200,10 +195,6 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) { // Body scale sourceBuffer += unpackFloatRatioFromTwoByte(sourceBuffer, _newScale); - // Follow mode info - _leaderUUID = QUuid::fromRfc4122(QByteArray((char*) sourceBuffer, NUM_BYTES_RFC4122_UUID)); - sourceBuffer += NUM_BYTES_RFC4122_UUID; - // Head rotation (NOTE: This needs to become a quaternion to save two bytes) float headYaw, headPitch, headRoll; sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*) sourceBuffer, &headYaw); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index e7f359aff2..0fa3aaa972 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -100,8 +100,6 @@ public: QString getQStringChatMessage() { return QString(_chatMessage.data()); } bool isChatCirclingEnabled() const { return _isChatCirclingEnabled; } - - const QUuid& getLeaderUUID() const { return _leaderUUID; } const HeadData* getHeadData() const { return _headData; } const HandData* getHandData() const { return _handData; } @@ -134,9 +132,6 @@ protected: // Body scale float _newScale; - // Following mode infos - QUuid _leaderUUID; - // Hand state (are we grabbing something or not) char _handState; diff --git a/libraries/octree-server/src/OctreeInboundPacketProcessor.cpp b/libraries/octree-server/src/OctreeInboundPacketProcessor.cpp index 020c1b274b..c88dfd16ac 100644 --- a/libraries/octree-server/src/OctreeInboundPacketProcessor.cpp +++ b/libraries/octree-server/src/OctreeInboundPacketProcessor.cpp @@ -57,7 +57,7 @@ void OctreeInboundPacketProcessor::processPacket(const HifiSockAddr& senderSockA PerformanceWarning warn(debugProcessPacket, "processPacket KNOWN TYPE",debugProcessPacket); _receivedPacketCount++; - Node* senderNode = NodeList::getInstance()->nodeWithAddress(senderSockAddr); + SharedNodePointer senderNode = NodeList::getInstance()->nodeWithAddress(senderSockAddr); unsigned short int sequence = (*((unsigned short int*)(packetData + numBytesPacketHeader))); uint64_t sentAt = (*((uint64_t*)(packetData + numBytesPacketHeader + sizeof(sequence)))); @@ -87,7 +87,9 @@ void OctreeInboundPacketProcessor::processPacket(const HifiSockAddr& senderSockA _myServer->getOctree()->lockForWrite(); uint64_t startProcess = usecTimestampNow(); int editDataBytesRead = _myServer->getOctree()->processEditPacketData(packetType, - packetData, packetLength, editData, maxSize, senderNode); + packetData, + packetLength, + editData, maxSize, senderNode.data()); _myServer->getOctree()->unlock(); uint64_t endProcess = usecTimestampNow(); diff --git a/libraries/octree-server/src/OctreeSendThread.cpp b/libraries/octree-server/src/OctreeSendThread.cpp index ccdf1ed8e2..41450022d2 100644 --- a/libraries/octree-server/src/OctreeSendThread.cpp +++ b/libraries/octree-server/src/OctreeSendThread.cpp @@ -30,7 +30,7 @@ bool OctreeSendThread::process() { // don't do any send processing until the initial load of the octree is complete... if (_myServer->isInitialLoadComplete()) { - Node* node = NodeList::getInstance()->nodeWithUUID(_nodeUUID); + SharedNodePointer node = NodeList::getInstance()->nodeWithUUID(_nodeUUID); if (node) { // make sure the node list doesn't kill our node while we're using it @@ -48,7 +48,7 @@ bool OctreeSendThread::process() { if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) { printf("nodeData->updateCurrentViewFrustum() changed=%s\n", debug::valueOf(viewFrustumChanged)); } - packetsSent = packetDistributor(node, nodeData, viewFrustumChanged); + packetsSent = packetDistributor(node.data(), nodeData, viewFrustumChanged); } node->unlock(); // we're done with this node for now. diff --git a/libraries/octree-server/src/OctreeServer.cpp b/libraries/octree-server/src/OctreeServer.cpp index 2a7f073ca4..1cfbf03ad8 100644 --- a/libraries/octree-server/src/OctreeServer.cpp +++ b/libraries/octree-server/src/OctreeServer.cpp @@ -27,11 +27,7 @@ void OctreeServer::attachQueryNodeToNode(Node* newNode) { } } -void OctreeServer::nodeAdded(Node* node) { - // do nothing -} - -void OctreeServer::nodeKilled(Node* node) { +void OctreeServer::nodeKilled(SharedNodePointer node) { // Use this to cleanup our node if (node->getType() == NODE_TYPE_AGENT) { OctreeQueryNode* nodeData = (OctreeQueryNode*)node->getLinkedData(); @@ -90,9 +86,6 @@ OctreeServer::~OctreeServer() { _persistThread->terminate(); delete _persistThread; } - - // tell our NodeList we're done with notifications - NodeList::getInstance()->removeHook(this); delete _jurisdiction; _jurisdiction = NULL; @@ -524,10 +517,10 @@ void OctreeServer::processDatagram(const QByteArray& dataByteArray, const HifiSo QUuid nodeUUID = QUuid::fromRfc4122(dataByteArray.mid(numBytesPacketHeader, NUM_BYTES_RFC4122_UUID)); - Node* node = nodeList->nodeWithUUID(nodeUUID); + SharedNodePointer node = nodeList->nodeWithUUID(nodeUUID); if (node) { - nodeList->updateNodeWithData(node, senderSockAddr, (unsigned char *) dataByteArray.data(), + nodeList->updateNodeWithData(node.data(), senderSockAddr, (unsigned char *) dataByteArray.data(), dataByteArray.size()); if (!node->getActiveSocket()) { // we don't have an active socket for this node, but they're talking to us @@ -612,7 +605,7 @@ void OctreeServer::run() { setvbuf(stdout, NULL, _IOLBF, 0); // tell our NodeList about our desire to get notifications - nodeList->addHook(this); + connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), SLOT(nodeKilled(SharedNodePointer))); nodeList->linkedDataCreateCallback = &OctreeServer::attachQueryNodeToNode; srand((unsigned)time(0)); diff --git a/libraries/octree-server/src/OctreeServer.h b/libraries/octree-server/src/OctreeServer.h index 39fb9ee990..f6380788a6 100644 --- a/libraries/octree-server/src/OctreeServer.h +++ b/libraries/octree-server/src/OctreeServer.h @@ -23,7 +23,7 @@ #include "OctreeInboundPacketProcessor.h" /// Handles assignments of type OctreeServer - sending octrees to various clients. -class OctreeServer : public ThreadedAssignment, public NodeListHook { +class OctreeServer : public ThreadedAssignment { public: OctreeServer(const unsigned char* dataBuffer, int numBytes); ~OctreeServer(); @@ -60,15 +60,13 @@ public: virtual int sendSpecialPacket(Node* node) { return 0; } static void attachQueryNodeToNode(Node* newNode); - - // NodeListHook - virtual void nodeAdded(Node* node); - virtual void nodeKilled(Node* node); - + public slots: /// runs the voxel server assignment void run(); void processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr); + + void nodeKilled(SharedNodePointer node); protected: int _argc; diff --git a/libraries/octree/src/JurisdictionListener.cpp b/libraries/octree/src/JurisdictionListener.cpp index 2080d0f2aa..29f6dde309 100644 --- a/libraries/octree/src/JurisdictionListener.cpp +++ b/libraries/octree/src/JurisdictionListener.cpp @@ -15,29 +15,20 @@ #include #include "JurisdictionListener.h" - JurisdictionListener::JurisdictionListener(NODE_TYPE type, PacketSenderNotify* notify) : PacketSender(notify, JurisdictionListener::DEFAULT_PACKETS_PER_SECOND) { _nodeType = type; ReceivedPacketProcessor::_dontSleep = true; // we handle sleeping so this class doesn't need to NodeList* nodeList = NodeList::getInstance(); - nodeList->addHook(this); - + + connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), SLOT(nodeKilled(SharedNodePointer))); + //qDebug("JurisdictionListener::JurisdictionListener(NODE_TYPE type=%c)\n", type); } -JurisdictionListener::~JurisdictionListener() { - NodeList* nodeList = NodeList::getInstance(); - nodeList->removeHook(this); -} - -void JurisdictionListener::nodeAdded(Node* node) { - // nothing to do. But need to implement it. -} - -void JurisdictionListener::nodeKilled(Node* node) { +void JurisdictionListener::nodeKilled(SharedNodePointer node) { if (_jurisdictions.find(node->getUUID()) != _jurisdictions.end()) { _jurisdictions.erase(_jurisdictions.find(node->getUUID())); } @@ -52,8 +43,9 @@ bool JurisdictionListener::queueJurisdictionRequest() { int nodeCount = 0; NodeList* nodeList = NodeList::getInstance(); - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { - if (nodeList->getNodeActiveSocketOrPing(&(*node)) && + + foreach(SharedNodePointer node, nodeList->getNodeHash()) { + if (nodeList->getNodeActiveSocketOrPing(&(*node)) && node->getType() == getNodeType()) { const HifiSockAddr* nodeAddress = node->getActiveSocket(); PacketSender::queuePacketForSending(*nodeAddress, bufferOut, sizeOut); @@ -73,7 +65,7 @@ bool JurisdictionListener::queueJurisdictionRequest() { void JurisdictionListener::processPacket(const HifiSockAddr& senderAddress, unsigned char* packetData, ssize_t packetLength) { if (packetData[0] == PACKET_TYPE_JURISDICTION) { - Node* node = NodeList::getInstance()->nodeWithAddress(senderAddress); + SharedNodePointer node = NodeList::getInstance()->nodeWithAddress(senderAddress); if (node) { QUuid nodeUUID = node->getUUID(); JurisdictionMap map; diff --git a/libraries/octree/src/JurisdictionListener.h b/libraries/octree/src/JurisdictionListener.h index b8951683a5..393ca80420 100644 --- a/libraries/octree/src/JurisdictionListener.h +++ b/libraries/octree/src/JurisdictionListener.h @@ -15,32 +15,32 @@ #include #include + #include "JurisdictionMap.h" /// Sends out PACKET_TYPE_JURISDICTION_REQUEST packets to all voxel servers and then listens for and processes /// the PACKET_TYPE_JURISDICTION packets it receives in order to maintain an accurate state of all jurisidictions /// within the domain. As with other ReceivedPacketProcessor classes the user is responsible for reading inbound packets /// and adding them to the processing queue by calling queueReceivedPacket() -class JurisdictionListener : public NodeListHook, public PacketSender, public ReceivedPacketProcessor { +class JurisdictionListener : public PacketSender, public ReceivedPacketProcessor { public: static const int DEFAULT_PACKETS_PER_SECOND = 1; static const int NO_SERVER_CHECK_RATE = 60; // if no servers yet detected, keep checking at 60fps JurisdictionListener(NODE_TYPE type = NODE_TYPE_VOXEL_SERVER, PacketSenderNotify* notify = NULL); - ~JurisdictionListener(); virtual bool process(); NodeToJurisdictionMap* getJurisdictions() { return &_jurisdictions; }; - /// Called by NodeList to inform us that a node has been added. - void nodeAdded(Node* node); - /// Called by NodeList to inform us that a node has been killed. - void nodeKilled(Node* node); NODE_TYPE getNodeType() const { return _nodeType; } void setNodeType(NODE_TYPE type) { _nodeType = type; } +public slots: + /// Called by NodeList to inform us that a node has been killed. + void nodeKilled(SharedNodePointer node); + protected: /// Callback for processing of received packets. Will process any queued PACKET_TYPE_JURISDICTION and update the /// jurisdiction map member variable diff --git a/libraries/octree/src/JurisdictionSender.cpp b/libraries/octree/src/JurisdictionSender.cpp index 289b2b2f07..24aeb1a51f 100644 --- a/libraries/octree/src/JurisdictionSender.cpp +++ b/libraries/octree/src/JurisdictionSender.cpp @@ -32,7 +32,7 @@ JurisdictionSender::~JurisdictionSender() { void JurisdictionSender::processPacket(const HifiSockAddr& senderAddress, unsigned char* packetData, ssize_t packetLength) { if (packetData[0] == PACKET_TYPE_JURISDICTION_REQUEST) { - Node* node = NodeList::getInstance()->nodeWithAddress(senderAddress); + SharedNodePointer node = NodeList::getInstance()->nodeWithAddress(senderAddress); if (node) { QUuid nodeUUID = node->getUUID(); lockRequestingNodes(); @@ -64,7 +64,7 @@ bool JurisdictionSender::process() { QUuid nodeUUID = _nodesRequestingJurisdictions.front(); _nodesRequestingJurisdictions.pop(); - Node* node = NodeList::getInstance()->nodeWithUUID(nodeUUID); + SharedNodePointer node = NodeList::getInstance()->nodeWithUUID(nodeUUID); if (node->getActiveSocket() != NULL) { const HifiSockAddr* nodeAddress = node->getActiveSocket(); diff --git a/libraries/octree/src/JurisdictionSender.h b/libraries/octree/src/JurisdictionSender.h index c3a47ffee3..1fc1e76d9b 100644 --- a/libraries/octree/src/JurisdictionSender.h +++ b/libraries/octree/src/JurisdictionSender.h @@ -21,6 +21,7 @@ /// to requesting parties. As with other ReceivedPacketProcessor classes the user is responsible for reading inbound packets /// and adding them to the processing queue by calling queueReceivedPacket() class JurisdictionSender : public PacketSender, public ReceivedPacketProcessor { + Q_OBJECT public: static const int DEFAULT_PACKETS_PER_SECOND = 1; diff --git a/libraries/octree/src/OctreeEditPacketSender.cpp b/libraries/octree/src/OctreeEditPacketSender.cpp index 9f7978c342..1367ca41bd 100644 --- a/libraries/octree/src/OctreeEditPacketSender.cpp +++ b/libraries/octree/src/OctreeEditPacketSender.cpp @@ -57,14 +57,15 @@ bool OctreeEditPacketSender::serversExist() const { bool hasServers = false; bool atLeastOnJurisdictionMissing = false; // assume the best NodeList* nodeList = NodeList::getInstance(); - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + + foreach(SharedNodePointer node, nodeList->getNodeHash()) { // only send to the NodeTypes that are getMyNodeType() if (node->getType() == getMyNodeType()) { if (nodeList->getNodeActiveSocketOrPing(&(*node))) { QUuid nodeUUID = node->getUUID(); // If we've got Jurisdictions set, then check to see if we know the jurisdiction for this server if (_serverJurisdictions) { - // lookup our nodeUUID in the jurisdiction map, if it's missing then we're + // lookup our nodeUUID in the jurisdiction map, if it's missing then we're // missing at least one jurisdiction if ((*_serverJurisdictions).find(nodeUUID) == (*_serverJurisdictions).end()) { atLeastOnJurisdictionMissing = true; @@ -77,6 +78,7 @@ bool OctreeEditPacketSender::serversExist() const { break; // no point in looking further... } } + return (hasServers && !atLeastOnJurisdictionMissing); } @@ -84,7 +86,8 @@ bool OctreeEditPacketSender::serversExist() const { // a known nodeID. void OctreeEditPacketSender::queuePacketToNode(const QUuid& nodeUUID, unsigned char* buffer, ssize_t length) { NodeList* nodeList = NodeList::getInstance(); - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + + foreach(SharedNodePointer node, nodeList->getNodeHash()) { // only send to the NodeTypes that are getMyNodeType() if (node->getType() == getMyNodeType() && ((node->getUUID() == nodeUUID) || (nodeUUID.isNull()))) { @@ -100,11 +103,11 @@ void OctreeEditPacketSender::queuePacketToNode(const QUuid& nodeUUID, unsigned c uint64_t createdAt = (*((uint64_t*)(buffer + numBytesPacketHeader + sizeof(sequence)))); uint64_t queuedAt = usecTimestampNow(); uint64_t transitTime = queuedAt - createdAt; - qDebug() << "OctreeEditPacketSender::queuePacketToNode() queued " << buffer[0] << - " - command to node bytes=" << length << - " sequence=" << sequence << - " transitTimeSoFar=" << transitTime << " usecs\n"; - } + qDebug() << "OctreeEditPacketSender::queuePacketToNode() queued " << buffer[0] << + " - command to node bytes=" << length << + " sequence=" << sequence << + " transitTimeSoFar=" << transitTime << " usecs\n"; + } } } } @@ -166,13 +169,13 @@ void OctreeEditPacketSender::queuePacketToNodes(unsigned char* buffer, ssize_t l // But we can't really do that with a packed message, since each edit message could be destined // for a different server... So we need to actually manage multiple queued packets... one // for each server - NodeList* nodeList = NodeList::getInstance(); - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + + foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) { // only send to the NodeTypes that are getMyNodeType() if (node->getActiveSocket() != NULL && node->getType() == getMyNodeType()) { QUuid nodeUUID = node->getUUID(); bool isMyJurisdiction = true; - // we need to get the jurisdiction for this + // we need to get the jurisdiction for this // here we need to get the "pending packet" for this server const JurisdictionMap& map = (*_serverJurisdictions)[nodeUUID]; isMyJurisdiction = (map.isMyJurisdiction(octCode, CHECK_NODE_ONLY) == JurisdictionMap::WITHIN); @@ -212,15 +215,15 @@ void OctreeEditPacketSender::queueOctreeEditMessage(PACKET_TYPE type, unsigned c // But we can't really do that with a packed message, since each edit message could be destined // for a different server... So we need to actually manage multiple queued packets... one // for each server - NodeList* nodeList = NodeList::getInstance(); - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + + foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) { // only send to the NodeTypes that are getMyNodeType() if (node->getActiveSocket() != NULL && node->getType() == getMyNodeType()) { QUuid nodeUUID = node->getUUID(); bool isMyJurisdiction = true; - + if (_serverJurisdictions) { - // we need to get the jurisdiction for this + // we need to get the jurisdiction for this // here we need to get the "pending packet" for this server if ((*_serverJurisdictions).find(nodeUUID) != (*_serverJurisdictions).end()) { const JurisdictionMap& map = (*_serverJurisdictions)[nodeUUID]; @@ -232,19 +235,19 @@ void OctreeEditPacketSender::queueOctreeEditMessage(PACKET_TYPE type, unsigned c if (isMyJurisdiction) { EditPacketBuffer& packetBuffer = _pendingEditPackets[nodeUUID]; packetBuffer._nodeUUID = nodeUUID; - + // If we're switching type, then we send the last one and start over - if ((type != packetBuffer._currentType && packetBuffer._currentSize > 0) || + if ((type != packetBuffer._currentType && packetBuffer._currentSize > 0) || (packetBuffer._currentSize + length >= _maxPacketSize)) { releaseQueuedPacket(packetBuffer); initializePacket(packetBuffer, type); } - + // If the buffer is empty and not correctly initialized for our type... if (type != packetBuffer._currentType && packetBuffer._currentSize == 0) { initializePacket(packetBuffer, type); } - + // This is really the first time we know which server/node this particular edit message // is going to, so we couldn't adjust for clock skew till now. But here's our chance. // We call this virtual function that allows our specific type of EditPacketSender to @@ -252,7 +255,7 @@ void OctreeEditPacketSender::queueOctreeEditMessage(PACKET_TYPE type, unsigned c if (node->getClockSkewUsec() != 0) { adjustEditPacketForClockSkew(codeColorBuffer, length, node->getClockSkewUsec()); } - + memcpy(&packetBuffer._currentBuffer[packetBuffer._currentSize], codeColorBuffer, length); packetBuffer._currentSize += length; } diff --git a/libraries/particles/src/ParticleCollisionSystem.cpp b/libraries/particles/src/ParticleCollisionSystem.cpp index 6711dc2d13..3ef831d9c7 100644 --- a/libraries/particles/src/ParticleCollisionSystem.cpp +++ b/libraries/particles/src/ParticleCollisionSystem.cpp @@ -187,22 +187,22 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) { } // loop through all the other avatars for potential interactions... - NodeList* nodeList = NodeList::getInstance(); - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + + foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) { //qDebug() << "updateCollisionWithAvatars()... node:" << *node << "\n"; if (node->getLinkedData() && node->getType() == NODE_TYPE_AGENT) { // TODO: dot collidingPalm and hand velocities and skip collision when they are moving apart. AvatarData* avatar = static_cast(node->getLinkedData()); //printf("updateCollisionWithAvatars()...avatar=%p\n", avatar); - + // check hands... const HandData* handData = avatar->getHandData(); - + if (handData->findSpherePenetration(center, radius, penetration, collidingPalm)) { // apply a hard collision when ball collides with hand penetration /= (float)(TREE_SCALE); updateCollisionSound(particle, penetration, COLLISION_FREQUENCY); - + // determine if the palm that collided was moving, if so, then we add that palm velocity as well... glm::vec3 addedVelocity = NO_ADDED_VELOCITY; if (collidingPalm) { @@ -210,9 +210,9 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) { //printf("collidingPalm Velocity=%f,%f,%f\n", palmVelocity.x, palmVelocity.y, palmVelocity.z); addedVelocity = palmVelocity; } - + applyHardCollision(particle, penetration, ELASTICITY, DAMPING, addedVelocity); - + } else if (avatar->findSpherePenetration(center, radius, penetration)) { penetration /= (float)(TREE_SCALE); updateCollisionSound(particle, penetration, COLLISION_FREQUENCY); diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 0a50a659b2..a4e3aaafae 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -52,10 +52,9 @@ NodeList* NodeList::getInstance() { } NodeList::NodeList(char newOwnerType, unsigned short int newSocketListenPort) : + _nodeHash(), _domainHostname(DEFAULT_DOMAIN_HOSTNAME), _domainSockAddr(HifiSockAddr(QHostAddress::Null, DEFAULT_DOMAIN_SERVER_PORT)), - _nodeBuckets(), - _numNodes(0), _nodeSocket(), _ownerType(newOwnerType), _nodeTypesOfInterest(NULL), @@ -108,10 +107,10 @@ void NodeList::setDomainHostname(const QString& domainHostname) { } void NodeList::timePingReply(const HifiSockAddr& nodeAddress, unsigned char *packetData) { - for(NodeList::iterator node = begin(); node != end(); node++) { + foreach(SharedNodePointer node, _nodeHash) { if (node->getPublicSocket() == nodeAddress || node->getLocalSocket() == nodeAddress) { - + unsigned char* dataAt = packetData + numBytesForPacketHeader(packetData); uint64_t ourOriginalTime = *(uint64_t*)(dataAt); dataAt += sizeof(ourOriginalTime); @@ -129,15 +128,15 @@ void NodeList::timePingReply(const HifiSockAddr& nodeAddress, unsigned char *pac node->setClockSkewUsec(clockSkew); const bool wantDebug = false; - if (wantDebug) { + if (wantDebug) { qDebug() << "PING_REPLY from node " << *node << "\n" << - " now: " << now << "\n" << - " ourTime: " << ourOriginalTime << "\n" << - " pingTime: " << pingTime << "\n" << - " oneWayFlightTime: " << oneWayFlightTime << "\n" << - " othersReplyTime: " << othersReplyTime << "\n" << - " othersExprectedReply: " << othersExprectedReply << "\n" << - " clockSkew: " << clockSkew << "\n"; + " now: " << now << "\n" << + " ourTime: " << ourOriginalTime << "\n" << + " pingTime: " << pingTime << "\n" << + " oneWayFlightTime: " << oneWayFlightTime << "\n" << + " othersReplyTime: " << othersReplyTime << "\n" << + " othersExprectedReply: " << othersExprectedReply << "\n" << + " clockSkew: " << clockSkew << "\n"; } break; } @@ -184,10 +183,9 @@ void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, unsigned char } void NodeList::processBulkNodeData(const HifiSockAddr& senderAddress, unsigned char *packetData, int numTotalBytes) { + SharedNodePointer bulkSendNode = nodeWithAddress(senderAddress); // find the avatar mixer in our node list and update the lastRecvTime from it - Node* bulkSendNode = nodeWithAddress(senderAddress); - if (bulkSendNode) { bulkSendNode->setLastHeardMicrostamp(usecTimestampNow()); @@ -209,14 +207,14 @@ void NodeList::processBulkNodeData(const HifiSockAddr& senderAddress, unsigned c numTotalBytes - (currentPosition - startPosition)); QUuid nodeUUID = QUuid::fromRfc4122(QByteArray((char*)currentPosition, NUM_BYTES_RFC4122_UUID)); - Node* matchingNode = nodeWithUUID(nodeUUID); + SharedNodePointer matchingNode = nodeWithUUID(nodeUUID); if (!matchingNode) { // we're missing this node, we need to add it to the list matchingNode = addOrUpdateNode(nodeUUID, NODE_TYPE_AGENT, HifiSockAddr(), HifiSockAddr()); } - currentPosition += updateNodeWithData(matchingNode, + currentPosition += updateNodeWithData(matchingNode.data(), HifiSockAddr(), packetHolder, numTotalBytes - (currentPosition - startPosition)); @@ -253,53 +251,39 @@ int NodeList::updateNodeWithData(Node *node, const HifiSockAddr& senderSockAddr, } } -Node* NodeList::nodeWithAddress(const HifiSockAddr &senderSockAddr) { - for(NodeList::iterator node = begin(); node != end(); node++) { +QSharedPointer NodeList::nodeWithAddress(const HifiSockAddr &senderSockAddr) { + // naively returns the first node that has a matching active HifiSockAddr + // note that there can be multiple nodes that have a matching active socket, so this isn't a good way to uniquely identify + foreach(QSharedPointer node, _nodeHash) { if (node->getActiveSocket() && *node->getActiveSocket() == senderSockAddr) { - return &(*node); + return node; } } - return NULL; + return QSharedPointer(NULL); } -Node* NodeList::nodeWithUUID(const QUuid& nodeUUID) { - for(NodeList::iterator node = begin(); node != end(); node++) { - if (node->getUUID() == nodeUUID) { - return &(*node); - } +QSharedPointer NodeList::nodeWithUUID(const QUuid& nodeUUID) { + QHash >::const_iterator foundIterator = _nodeHash.find(nodeUUID); + if (foundIterator != _nodeHash.end()) { + return foundIterator.value(); + } else { + return QSharedPointer(NULL); } - - return NULL; -} - -int NodeList::getNumAliveNodes() const { - int numAliveNodes = 0; - - for (NodeList::iterator node = begin(); node != end(); node++) { - if (node->isAlive()) { - ++numAliveNodes; - } - } - - return numAliveNodes; } void NodeList::clear() { qDebug() << "Clearing the NodeList. Deleting all nodes in list.\n"; - // delete all of the nodes in the list, set the pointers back to NULL and the number of nodes to 0 - for (int i = 0; i < _numNodes; i++) { - Node** nodeBucket = _nodeBuckets[i / NODES_PER_BUCKET]; - Node* node = nodeBucket[i % NODES_PER_BUCKET]; - - node->lock(); - notifyHooksOfKilledNode(&*node); - - delete node; - } + NodeHash::iterator nodeItem = _nodeHash.begin(); - _numNodes = 0; + // iterate the nodes in the list + while (nodeItem != _nodeHash.end()) { + // emit our signal to say this node has been killed + emit nodeKilled(nodeItem.value()); + // erase the node from our node hash + _nodeHash.erase(nodeItem); + } } void NodeList::reset() { @@ -457,6 +441,14 @@ void NodeList::processSTUNResponse(unsigned char* packetData, size_t dataBytes) } } +void NodeList::killNodeWithUUID(const QUuid& nodeUUID) { + NodeHash::iterator nodeToKill = _nodeHash.find(nodeUUID); + if (nodeToKill != _nodeHash.end()) { + emit nodeKilled(nodeToKill.value()); + _nodeHash.erase(nodeToKill); + } +} + void NodeList::sendKillNode(const char* nodeTypes, int numNodeTypes) { unsigned char packet[MAX_PACKET_SIZE]; unsigned char* packetPosition = packet; @@ -483,9 +475,10 @@ void NodeList::processKillNode(unsigned char* packetData, size_t dataBytes) { dataBytes -= NUM_BYTES_RFC4122_UUID; // make sure the node exists - Node* node = nodeWithUUID(nodeUUID); - if (node) { - killNode(node, true); + NodeHash::iterator nodeToKill = _nodeHash.find(nodeUUID); + if (nodeToKill != _nodeHash.end()) { + emit nodeKilled(nodeToKill.value()); + _nodeHash.erase(nodeToKill); } } @@ -681,26 +674,24 @@ void NodeList::pingPublicAndLocalSocketsForInactiveNode(Node* node) { node->getPublicSocket().getAddress(), node->getPublicSocket().getPort()); } -Node* NodeList::addOrUpdateNode(const QUuid& uuid, char nodeType, +SharedNodePointer NodeList::addOrUpdateNode(const QUuid& uuid, char nodeType, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket) { - NodeList::iterator node = end(); + NodeHash::iterator matchingNodeItem = _nodeHash.find(uuid); - for (node = begin(); node != end(); node++) { - if (node->getUUID() == uuid) { - // we already have this node, stop checking - break; - } - } - - if (node == end()) { + if (matchingNodeItem == _nodeHash.end()) { // we didn't have this node, so add them Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket); - addNodeToList(newNode); + NodeHash::iterator addedItem = _nodeHash.insert(newNode->getUUID(), SharedNodePointer(newNode)); - return newNode; + qDebug() << "Added" << *newNode << "\n"; + + emit nodeAdded(addedItem.value()); + + return SharedNodePointer(newNode); } else { - node->lock(); + SharedNodePointer node = matchingNodeItem.value(); + matchingNodeItem.value()->lock(); if (node->getType() == NODE_TYPE_AUDIO_MIXER || node->getType() == NODE_TYPE_VOXEL_SERVER || @@ -724,33 +715,17 @@ Node* NodeList::addOrUpdateNode(const QUuid& uuid, char nodeType, node->unlock(); // we had this node already, do nothing for now - return &*node; + return node; } } -void NodeList::addNodeToList(Node* newNode) { - // find the correct array to add this node to - int bucketIndex = _numNodes / NODES_PER_BUCKET; - - if (!_nodeBuckets[bucketIndex]) { - _nodeBuckets[bucketIndex] = new Node*[NODES_PER_BUCKET](); - } - - _nodeBuckets[bucketIndex][_numNodes % NODES_PER_BUCKET] = newNode; - - ++_numNodes; - - qDebug() << "Added" << *newNode << "\n"; - - notifyHooksOfAddedNode(newNode); -} - unsigned NodeList::broadcastToNodes(unsigned char* broadcastData, size_t dataBytes, const char* nodeTypes, int numNodeTypes) { unsigned n = 0; - for(NodeList::iterator node = begin(); node != end(); node++) { + + foreach(SharedNodePointer node, _nodeHash) { // only send to the NodeTypes we are asked to send to. if (memchr(nodeTypes, node->getType(), numNodeTypes)) { - if (getNodeActiveSocketOrPing(&(*node))) { + if (getNodeActiveSocketOrPing(node.data())) { // we know which socket is good for this node, send there _nodeSocket.writeDatagram((char*) broadcastData, dataBytes, node->getActiveSocket()->getAddress(), node->getActiveSocket()->getPort()); @@ -758,14 +733,15 @@ unsigned NodeList::broadcastToNodes(unsigned char* broadcastData, size_t dataByt } } } + return n; } void NodeList::pingInactiveNodes() { - for(NodeList::iterator node = begin(); node != end(); node++) { + foreach(SharedNodePointer node, _nodeHash) { if (!node->getActiveSocket()) { // we don't have an active link to this node, ping it to set that up - pingPublicAndLocalSocketsForInactiveNode(&(*node)); + pingPublicAndLocalSocketsForInactiveNode(node.data()); } } } @@ -780,7 +756,8 @@ const HifiSockAddr* NodeList::getNodeActiveSocketOrPing(Node* node) { } void NodeList::activateSocketFromNodeCommunication(const HifiSockAddr& nodeAddress) { - for(NodeList::iterator node = begin(); node != end(); node++) { + + foreach(SharedNodePointer node, _nodeHash) { if (!node->getActiveSocket()) { // check both the public and local addresses for each node to see if we find a match // prioritize the private address so that we prune erroneous local matches @@ -795,46 +772,35 @@ void NodeList::activateSocketFromNodeCommunication(const HifiSockAddr& nodeAddre } } -Node* NodeList::soloNodeOfType(char nodeType) { +SharedNodePointer NodeList::soloNodeOfType(char nodeType) { + if (memchr(SOLO_NODE_TYPES, nodeType, sizeof(SOLO_NODE_TYPES)) != NULL) { - for(NodeList::iterator node = begin(); node != end(); node++) { + foreach(SharedNodePointer node, _nodeHash) { if (node->getType() == nodeType) { - return &(*node); + return node; } } } - return NULL; -} - -void NodeList::killNode(Node* node, bool mustLockNode) { - if (mustLockNode) { - node->lock(); - } - - qDebug() << "Killed " << *node << "\n"; - - notifyHooksOfKilledNode(&*node); - - node->setAlive(false); - - if (mustLockNode) { - node->unlock(); - } + return SharedNodePointer(NULL); } void NodeList::removeSilentNodes() { - NodeList* nodeList = NodeList::getInstance(); - for(NodeList::iterator node = nodeList->begin(); node != nodeList->end(); ++node) { - node->lock(); + NodeHash::iterator nodeItem = _nodeHash.begin(); + + while (nodeItem != _nodeHash.end()) { + nodeItem.value()->lock(); - if ((usecTimestampNow() - node->getLastHeardMicrostamp()) > NODE_SILENCE_THRESHOLD_USECS) { + if ((usecTimestampNow() - nodeItem.value()->getLastHeardMicrostamp()) > NODE_SILENCE_THRESHOLD_USECS) { + SharedNodePointer node = nodeItem.value(); + // kill this node, don't lock - we already did it - nodeList->killNode(&(*node), false); + _nodeHash.erase(nodeItem); + + // unlock the node + node->unlock(); } - - node->unlock(); } } @@ -868,80 +834,6 @@ void NodeList::saveData(QSettings* settings) { settings->endGroup(); } -NodeList::iterator NodeList::begin() const { - Node** nodeBucket = NULL; - - for (int i = 0; i < _numNodes; i++) { - if (i % NODES_PER_BUCKET == 0) { - nodeBucket = _nodeBuckets[i / NODES_PER_BUCKET]; - } - - if (nodeBucket[i % NODES_PER_BUCKET]->isAlive()) { - return NodeListIterator(this, i); - } - } - - // there's no alive node to start from - return the end - return end(); -} - -NodeList::iterator NodeList::end() const { - return NodeListIterator(this, _numNodes); -} - -NodeListIterator::NodeListIterator(const NodeList* nodeList, int nodeIndex) : - _nodeIndex(nodeIndex) { - _nodeList = nodeList; -} - -NodeListIterator& NodeListIterator::operator=(const NodeListIterator& otherValue) { - _nodeList = otherValue._nodeList; - _nodeIndex = otherValue._nodeIndex; - return *this; -} - -bool NodeListIterator::operator==(const NodeListIterator &otherValue) { - return _nodeIndex == otherValue._nodeIndex; -} - -bool NodeListIterator::operator!=(const NodeListIterator &otherValue) { - return !(*this == otherValue); -} - -Node& NodeListIterator::operator*() { - Node** nodeBucket = _nodeList->_nodeBuckets[_nodeIndex / NODES_PER_BUCKET]; - return *nodeBucket[_nodeIndex % NODES_PER_BUCKET]; -} - -Node* NodeListIterator::operator->() { - Node** nodeBucket = _nodeList->_nodeBuckets[_nodeIndex / NODES_PER_BUCKET]; - return nodeBucket[_nodeIndex % NODES_PER_BUCKET]; -} - -NodeListIterator& NodeListIterator::operator++() { - skipDeadAndStopIncrement(); - return *this; -} - -NodeList::iterator NodeListIterator::operator++(int) { - NodeListIterator newIterator = NodeListIterator(*this); - skipDeadAndStopIncrement(); - return newIterator; -} - -void NodeListIterator::skipDeadAndStopIncrement() { - while (_nodeIndex != _nodeList->_numNodes) { - ++_nodeIndex; - - if (_nodeIndex == _nodeList->_numNodes) { - break; - } else if ((*(*this)).isAlive()) { - // skip over the dead nodes - break; - } - } -} - void NodeList::addDomainListener(DomainChangeListener* listener) { _domainListeners.push_back(listener); QString domain = _domainHostname.isEmpty() ? _domainSockAddr.getAddress().toString() : _domainHostname; @@ -957,33 +849,6 @@ void NodeList::removeDomainListener(DomainChangeListener* listener) { } } -void NodeList::addHook(NodeListHook* hook) { - _hooks.push_back(hook); -} - -void NodeList::removeHook(NodeListHook* hook) { - for (int i = 0; i < _hooks.size(); i++) { - if (_hooks[i] == hook) { - _hooks.erase(_hooks.begin() + i); - return; - } - } -} - -void NodeList::notifyHooksOfAddedNode(Node* node) { - for (int i = 0; i < _hooks.size(); i++) { - //printf("NodeList::notifyHooksOfAddedNode() i=%d\n", i); - _hooks[i]->nodeAdded(node); - } -} - -void NodeList::notifyHooksOfKilledNode(Node* node) { - for (int i = 0; i < _hooks.size(); i++) { - //printf("NodeList::notifyHooksOfKilledNode() i=%d\n", i); - _hooks[i]->nodeKilled(node); - } -} - void NodeList::notifyDomainChanged() { for (int i = 0; i < _domainListeners.size(); i++) { _domainListeners[i]->domainChanged(_domainHostname); diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index 47cdbac99d..e139eb62f2 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -14,9 +14,10 @@ #include #include +#include +#include #include #include -#include #include "Node.h" #include "NodeTypes.h" @@ -43,31 +44,21 @@ const int MAX_SILENT_DOMAIN_SERVER_CHECK_INS = 5; class Assignment; class HifiSockAddr; -class NodeListIterator; - -// Callers who want to hook add/kill callbacks should implement this class -class NodeListHook { -public: - virtual void nodeAdded(Node* node) = 0; - virtual void nodeKilled(Node* node) = 0; -}; class DomainChangeListener { public: virtual void domainChanged(QString domain) = 0; }; +typedef QSharedPointer SharedNodePointer; +typedef QHash NodeHash; + class NodeList : public QObject { Q_OBJECT public: static NodeList* createInstance(char ownerType, unsigned short int socketListenPort = 0); static NodeList* getInstance(); - typedef NodeListIterator iterator; - - NodeListIterator begin() const; - NodeListIterator end() const; - NODE_TYPE getOwnerType() const { return _ownerType; } void setOwnerType(NODE_TYPE ownerType) { _ownerType = ownerType; } @@ -88,8 +79,9 @@ public: void(*linkedDataCreateCallback)(Node *); - int size() { return _numNodes; } - int getNumAliveNodes() const; + const NodeHash& getNodeHash() { return _nodeHash; } + + int size() const { return _nodeHash.size(); } int getNumNoReplyDomainCheckIns() const { return _numNoReplyDomainCheckIns; } @@ -107,13 +99,13 @@ public: int fillPingReplyPacket(unsigned char* pingBuffer, unsigned char* replyBuffer); void pingPublicAndLocalSocketsForInactiveNode(Node* node); + void killNodeWithUUID(const QUuid& nodeUUID); void sendKillNode(const char* nodeTypes, int numNodeTypes); - Node* nodeWithAddress(const HifiSockAddr& senderSockAddr); - Node* nodeWithUUID(const QUuid& nodeUUID); + SharedNodePointer nodeWithAddress(const HifiSockAddr& senderSockAddr); + SharedNodePointer nodeWithUUID(const QUuid& nodeUUID); - Node* addOrUpdateNode(const QUuid& uuid, char nodeType, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket); - void killNode(Node* node, bool mustLockNode = true); + SharedNodePointer addOrUpdateNode(const QUuid& uuid, char nodeType, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket); void processNodeData(const HifiSockAddr& senderSockAddr, unsigned char *packetData, size_t dataBytes); void processBulkNodeData(const HifiSockAddr& senderSockAddr, unsigned char *packetData, int numTotalBytes); @@ -122,18 +114,11 @@ public: unsigned broadcastToNodes(unsigned char *broadcastData, size_t dataBytes, const char* nodeTypes, int numNodeTypes); - Node* soloNodeOfType(char nodeType); + SharedNodePointer soloNodeOfType(char nodeType); void loadData(QSettings* settings); void saveData(QSettings* settings); - friend class NodeListIterator; - - void addHook(NodeListHook* hook); - void removeHook(NodeListHook* hook); - void notifyHooksOfAddedNode(Node* node); - void notifyHooksOfKilledNode(Node* node); - void addDomainListener(DomainChangeListener* listener); void removeDomainListener(DomainChangeListener* listener); @@ -142,6 +127,9 @@ public slots: void sendDomainServerCheckIn(); void pingInactiveNodes(); void removeSilentNodes(); +signals: + void nodeAdded(QSharedPointer); + void nodeKilled(QSharedPointer); private: static NodeList* _sharedInstance; @@ -150,17 +138,14 @@ private: NodeList(NodeList const&); // Don't implement, needed to avoid copies of singleton void operator=(NodeList const&); // Don't implement, needed to avoid copies of singleton - void addNodeToList(Node* newNode); - void sendSTUNRequest(); void processSTUNResponse(unsigned char* packetData, size_t dataBytes); void processKillNode(unsigned char* packetData, size_t dataBytes); + NodeHash _nodeHash; QString _domainHostname; HifiSockAddr _domainSockAddr; - Node** _nodeBuckets[MAX_NUM_NODES / NODES_PER_BUCKET]; - int _numNodes; QUdpSocket _nodeSocket; char _ownerType; char* _nodeTypesOfInterest; @@ -174,7 +159,6 @@ private: void activateSocketFromNodeCommunication(const HifiSockAddr& nodeSockAddr); void timePingReply(const HifiSockAddr& nodeAddress, unsigned char *packetData); - std::vector _hooks; std::vector _domainListeners; void resetDomainData(char domainField[], const char* domainData); @@ -182,27 +166,4 @@ private: void domainLookup(); }; -class NodeListIterator : public std::iterator { -public: - NodeListIterator(const NodeList* nodeList, int nodeIndex); - - int getNodeIndex() { return _nodeIndex; } - - NodeListIterator& operator=(const NodeListIterator& otherValue); - - bool operator==(const NodeListIterator& otherValue); - bool operator!= (const NodeListIterator& otherValue); - - Node& operator*(); - Node* operator->(); - - NodeListIterator& operator++(); - NodeListIterator operator++(int); -private: - void skipDeadAndStopIncrement(); - - const NodeList* _nodeList; - int _nodeIndex; -}; - #endif /* defined(__hifi__NodeList__) */ diff --git a/libraries/shared/src/ReceivedPacketProcessor.cpp b/libraries/shared/src/ReceivedPacketProcessor.cpp index 4ad869460e..d61db2b184 100644 --- a/libraries/shared/src/ReceivedPacketProcessor.cpp +++ b/libraries/shared/src/ReceivedPacketProcessor.cpp @@ -18,7 +18,7 @@ ReceivedPacketProcessor::ReceivedPacketProcessor() { void ReceivedPacketProcessor::queueReceivedPacket(const HifiSockAddr& address, unsigned char* packetData, ssize_t packetLength) { // Make sure our Node and NodeList knows we've heard from this node. - Node* node = NodeList::getInstance()->nodeWithAddress(address); + SharedNodePointer node = NodeList::getInstance()->nodeWithAddress(address); if (node) { node->setLastHeardMicrostamp(usecTimestampNow()); } From 677303b5c03932108775e77d50a2355d56f6f1a4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 13 Jan 2014 17:17:53 -0800 Subject: [PATCH 09/29] properly hook SharedNodePointer for signals/slots --- libraries/shared/src/Node.h | 3 ++- libraries/shared/src/NodeList.cpp | 5 ++++- libraries/shared/src/NodeList.h | 5 +++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/libraries/shared/src/Node.h b/libraries/shared/src/Node.h index 96f16a31d4..fe6e95dac8 100644 --- a/libraries/shared/src/Node.h +++ b/libraries/shared/src/Node.h @@ -25,7 +25,8 @@ #include "NodeData.h" #include "SimpleMovingAverage.h" -class Node { +class Node : public QObject { + Q_OBJECT public: Node(const QUuid& uuid, char type, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket); ~Node(); diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index a4e3aaafae..46bc8391e5 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -36,6 +36,9 @@ NodeList* NodeList::_sharedInstance = NULL; NodeList* NodeList::createInstance(char ownerType, unsigned short int socketListenPort) { if (!_sharedInstance) { _sharedInstance = new NodeList(ownerType, socketListenPort); + + // register the SharedNodePointer meta-type for signals/slots + qRegisterMetaType(); } else { qDebug("NodeList createInstance called with existing instance."); } @@ -682,7 +685,7 @@ SharedNodePointer NodeList::addOrUpdateNode(const QUuid& uuid, char nodeType, // we didn't have this node, so add them Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket); - NodeHash::iterator addedItem = _nodeHash.insert(newNode->getUUID(), SharedNodePointer(newNode)); + NodeHash::iterator addedItem = _nodeHash.insert(newNode->getUUID(), SharedNodePointer(newNode, &QObject::deleteLater)); qDebug() << "Added" << *newNode << "\n"; diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index e139eb62f2..efb08f32d1 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -52,6 +52,7 @@ public: typedef QSharedPointer SharedNodePointer; typedef QHash NodeHash; +Q_DECLARE_METATYPE(SharedNodePointer) class NodeList : public QObject { Q_OBJECT @@ -128,8 +129,8 @@ public slots: void pingInactiveNodes(); void removeSilentNodes(); signals: - void nodeAdded(QSharedPointer); - void nodeKilled(QSharedPointer); + void nodeAdded(SharedNodePointer); + void nodeKilled(SharedNodePointer); private: static NodeList* _sharedInstance; From 6a0c431562c71d28ebf52a3059ac92da91e32b30 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 13 Jan 2014 17:29:45 -0800 Subject: [PATCH 10/29] repair add of new node (so it doesn't immediately kill) --- libraries/shared/src/Node.cpp | 2 ++ libraries/shared/src/NodeList.cpp | 7 ++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/libraries/shared/src/Node.cpp b/libraries/shared/src/Node.cpp index 739c1c03a9..36ee1682a6 100644 --- a/libraries/shared/src/Node.cpp +++ b/libraries/shared/src/Node.cpp @@ -39,6 +39,8 @@ Node::Node(const QUuid& uuid, char type, const HifiSockAddr& publicSocket, const } Node::~Node() { + qDebug() << "Destructor for node with UUID" << _uuid << "called.\n"; + if (_linkedData) { _linkedData->deleteOrDeleteLater(); } diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 46bc8391e5..fc6dc1851e 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -684,14 +684,15 @@ SharedNodePointer NodeList::addOrUpdateNode(const QUuid& uuid, char nodeType, if (matchingNodeItem == _nodeHash.end()) { // we didn't have this node, so add them Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket); + SharedNodePointer newNodeSharedPointer(newNode, &QObject::deleteLater); - NodeHash::iterator addedItem = _nodeHash.insert(newNode->getUUID(), SharedNodePointer(newNode, &QObject::deleteLater)); + _nodeHash.insert(newNode->getUUID(), newNodeSharedPointer); qDebug() << "Added" << *newNode << "\n"; - emit nodeAdded(addedItem.value()); + emit nodeAdded(newNodeSharedPointer); - return SharedNodePointer(newNode); + return newNodeSharedPointer; } else { SharedNodePointer node = matchingNodeItem.value(); matchingNodeItem.value()->lock(); From 0579b1842645d290ff150e82852d2830130ad86a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 13 Jan 2014 17:33:58 -0800 Subject: [PATCH 11/29] fix deadlock in silent node removal --- libraries/shared/src/NodeList.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index fc6dc1851e..bf4bb16d70 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -794,17 +794,19 @@ void NodeList::removeSilentNodes() { NodeHash::iterator nodeItem = _nodeHash.begin(); while (nodeItem != _nodeHash.end()) { - nodeItem.value()->lock(); - if ((usecTimestampNow() - nodeItem.value()->getLastHeardMicrostamp()) > NODE_SILENCE_THRESHOLD_USECS) { - SharedNodePointer node = nodeItem.value(); + SharedNodePointer node = nodeItem.value(); + + node->lock(); + + if ((usecTimestampNow() - node->getLastHeardMicrostamp()) > NODE_SILENCE_THRESHOLD_USECS) { // kill this node, don't lock - we already did it _nodeHash.erase(nodeItem); - - // unlock the node - node->unlock(); } + + // unlock the node + node->unlock(); } } From 1faa2120aa76242ec46c9979b803b6396d61f190 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 13 Jan 2014 17:36:27 -0800 Subject: [PATCH 12/29] use typedef in NodeList implementation --- libraries/shared/src/NodeList.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index bf4bb16d70..9d47806f18 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -254,24 +254,24 @@ int NodeList::updateNodeWithData(Node *node, const HifiSockAddr& senderSockAddr, } } -QSharedPointer NodeList::nodeWithAddress(const HifiSockAddr &senderSockAddr) { +SharedNodePointer NodeList::nodeWithAddress(const HifiSockAddr &senderSockAddr) { // naively returns the first node that has a matching active HifiSockAddr // note that there can be multiple nodes that have a matching active socket, so this isn't a good way to uniquely identify - foreach(QSharedPointer node, _nodeHash) { + foreach(SharedNodePointer node, _nodeHash) { if (node->getActiveSocket() && *node->getActiveSocket() == senderSockAddr) { return node; } } - return QSharedPointer(NULL); + return SharedNodePointer(); } -QSharedPointer NodeList::nodeWithUUID(const QUuid& nodeUUID) { +SharedNodePointer NodeList::nodeWithUUID(const QUuid& nodeUUID) { QHash >::const_iterator foundIterator = _nodeHash.find(nodeUUID); if (foundIterator != _nodeHash.end()) { return foundIterator.value(); } else { - return QSharedPointer(NULL); + return SharedNodePointer(); } } From 3ab7a6d9d5ffbda3413b8d27e45b95628f5b2af8 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 13 Jan 2014 17:58:48 -0800 Subject: [PATCH 13/29] move network packet processing to main thread --- interface/src/Application.cpp | 190 +++++++++++++----------------- interface/src/Application.h | 6 +- libraries/shared/src/NodeList.cpp | 2 +- 3 files changed, 85 insertions(+), 113 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e28114034b..7b82bc8d25 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -128,7 +128,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _perfStatsOn(false), _chatEntryOn(false), _audio(&_audioScope, STARTUP_JITTER_SAMPLES), - _stopNetworkReceiveThread(false), + _enableProcessVoxelsThread(true), _voxelProcessor(), _voxelHideShowThread(&_voxels), _voxelEditSender(this), @@ -165,6 +165,9 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : } NodeList* nodeList = NodeList::createInstance(NODE_TYPE_AGENT, listenPort); + + // connect our processDatagrams slot to the QUDPSocket readyRead() signal + connect(&nodeList->getNodeSocket(), SIGNAL(readyRead()), SLOT(processDatagrams())); // put the audio processing on a separate thread QThread* audioThread = new QThread(this); @@ -180,9 +183,6 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : nodeList->addDomainListener(this); - // network receive thread and voxel parsing thread are both controlled by the --nonblocking command line - _enableProcessVoxelsThread = _enableNetworkThread = !cmdOptionExists(argc, constArgv, "--nonblocking"); - // read the ApplicationInfo.ini file for Name/Version/Domain information QSettings applicationInfo("resources/info/ApplicationInfo.ini", QSettings::IniFormat); @@ -330,12 +330,6 @@ void Application::initializeGL() { init(); qDebug( "Init() complete.\n" ); - // create thread for receipt of data via UDP - if (_enableNetworkThread) { - pthread_create(&_networkReceiveThread, NULL, networkReceive, NULL); - qDebug("Network receive thread created.\n"); - } - // create thread for parsing of voxel data independent of the main network and rendering threads _voxelProcessor.initialize(_enableProcessVoxelsThread); _voxelEditSender.initialize(_enableProcessVoxelsThread); @@ -1424,11 +1418,6 @@ void Application::terminate() { // let the avatar mixer know we're out NodeList::getInstance()->sendKillNode(&NODE_TYPE_AVATAR_MIXER, 1); - if (_enableNetworkThread) { - _stopNetworkReceiveThread = true; - pthread_join(_networkReceiveThread, NULL); - } - printf(""); _voxelProcessor.terminate(); _voxelHideShowThread.terminate(); @@ -2322,11 +2311,6 @@ void Application::updateThreads(float deltaTime) { bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::updateThreads()"); - // read incoming packets from network - if (!_enableNetworkThread) { - networkReceive(0); - } - // parse voxel packets if (!_enableProcessVoxelsThread) { _voxelProcessor.threadRoutine(); @@ -4272,105 +4256,95 @@ int Application::parseOctreeStats(unsigned char* messageData, ssize_t messageLen } // Receive packets from other nodes/servers and decide what to do with them! -void* Application::networkReceive(void* args) { +void Application::processDatagrams() { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::networkReceive()"); HifiSockAddr senderSockAddr; ssize_t bytesReceived; - Application* app = Application::getInstance(); - while (!app->_stopNetworkReceiveThread) { - if (NodeList::getInstance()->getNodeSocket().hasPendingDatagrams() && - (bytesReceived = NodeList::getInstance()->getNodeSocket().readDatagram((char*) app->_incomingPacket, - MAX_PACKET_SIZE, - senderSockAddr.getAddressPointer(), - senderSockAddr.getPortPointer()))) { - - app->_packetCount++; - app->_bytesCount += bytesReceived; - - if (packetVersionMatch(app->_incomingPacket)) { - // only process this packet if we have a match on the packet version - switch (app->_incomingPacket[0]) { - case PACKET_TYPE_TRANSMITTER_DATA_V2: - // V2 = IOS transmitter app - app->_myTransmitter.processIncomingData(app->_incomingPacket, bytesReceived); - - break; - case PACKET_TYPE_MIXED_AUDIO: - QMetaObject::invokeMethod(&app->_audio, "addReceivedAudioToBuffer", Qt::QueuedConnection, - Q_ARG(QByteArray, QByteArray((char*) app->_incomingPacket, bytesReceived))); - break; - - case PACKET_TYPE_PARTICLE_ADD_RESPONSE: - // look up our ParticleEditHanders.... - ParticleEditHandle::handleAddResponse(app->_incomingPacket, bytesReceived); - break; - - case PACKET_TYPE_PARTICLE_DATA: - case PACKET_TYPE_VOXEL_DATA: - case PACKET_TYPE_VOXEL_ERASE: - case PACKET_TYPE_OCTREE_STATS: - case PACKET_TYPE_ENVIRONMENT_DATA: { - PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), - "Application::networkReceive()... _voxelProcessor.queueReceivedPacket()"); - - bool wantExtraDebugging = app->getLogger()->extraDebugging(); - if (wantExtraDebugging && app->_incomingPacket[0] == PACKET_TYPE_VOXEL_DATA) { - int numBytesPacketHeader = numBytesForPacketHeader(app->_incomingPacket); - unsigned char* dataAt = app->_incomingPacket + numBytesPacketHeader; - dataAt += sizeof(VOXEL_PACKET_FLAGS); - VOXEL_PACKET_SEQUENCE sequence = (*(VOXEL_PACKET_SEQUENCE*)dataAt); - dataAt += sizeof(VOXEL_PACKET_SEQUENCE); - VOXEL_PACKET_SENT_TIME sentAt = (*(VOXEL_PACKET_SENT_TIME*)dataAt); - dataAt += sizeof(VOXEL_PACKET_SENT_TIME); - VOXEL_PACKET_SENT_TIME arrivedAt = usecTimestampNow(); - int flightTime = arrivedAt - sentAt; - - printf("got PACKET_TYPE_VOXEL_DATA, sequence:%d flightTime:%d\n", sequence, flightTime); - } - - // add this packet to our list of voxel packets and process them on the voxel processing - app->_voxelProcessor.queueReceivedPacket(senderSockAddr, app->_incomingPacket, bytesReceived); - break; + if (NodeList::getInstance()->getNodeSocket().hasPendingDatagrams() && + (bytesReceived = NodeList::getInstance()->getNodeSocket().readDatagram((char*) _incomingPacket, + MAX_PACKET_SIZE, + senderSockAddr.getAddressPointer(), + senderSockAddr.getPortPointer()))) { + + _packetCount++; + _bytesCount += bytesReceived; + + if (packetVersionMatch(_incomingPacket)) { + // only process this packet if we have a match on the packet version + switch (_incomingPacket[0]) { + case PACKET_TYPE_TRANSMITTER_DATA_V2: + // V2 = IOS transmitter app + _myTransmitter.processIncomingData(_incomingPacket, bytesReceived); + + break; + case PACKET_TYPE_MIXED_AUDIO: + QMetaObject::invokeMethod(&_audio, "addReceivedAudioToBuffer", Qt::QueuedConnection, + Q_ARG(QByteArray, QByteArray((char*) _incomingPacket, bytesReceived))); + break; + + case PACKET_TYPE_PARTICLE_ADD_RESPONSE: + // look up our ParticleEditHanders.... + ParticleEditHandle::handleAddResponse(_incomingPacket, bytesReceived); + break; + + case PACKET_TYPE_PARTICLE_DATA: + case PACKET_TYPE_VOXEL_DATA: + case PACKET_TYPE_VOXEL_ERASE: + case PACKET_TYPE_OCTREE_STATS: + case PACKET_TYPE_ENVIRONMENT_DATA: { + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), + "Application::networkReceive()... _voxelProcessor.queueReceivedPacket()"); + + bool wantExtraDebugging = getLogger()->extraDebugging(); + if (wantExtraDebugging && _incomingPacket[0] == PACKET_TYPE_VOXEL_DATA) { + int numBytesPacketHeader = numBytesForPacketHeader(_incomingPacket); + unsigned char* dataAt = _incomingPacket + numBytesPacketHeader; + dataAt += sizeof(VOXEL_PACKET_FLAGS); + VOXEL_PACKET_SEQUENCE sequence = (*(VOXEL_PACKET_SEQUENCE*)dataAt); + dataAt += sizeof(VOXEL_PACKET_SEQUENCE); + VOXEL_PACKET_SENT_TIME sentAt = (*(VOXEL_PACKET_SENT_TIME*)dataAt); + dataAt += sizeof(VOXEL_PACKET_SENT_TIME); + VOXEL_PACKET_SENT_TIME arrivedAt = usecTimestampNow(); + int flightTime = arrivedAt - sentAt; + + printf("got PACKET_TYPE_VOXEL_DATA, sequence:%d flightTime:%d\n", sequence, flightTime); } - case PACKET_TYPE_METAVOXEL_DATA: - app->_metavoxels.processData(QByteArray((const char*)app->_incomingPacket, bytesReceived), - senderSockAddr); - break; - case PACKET_TYPE_BULK_AVATAR_DATA: - NodeList::getInstance()->processBulkNodeData(senderSockAddr, - app->_incomingPacket, - bytesReceived); - getInstance()->_bandwidthMeter.inputStream(BandwidthMeter::AVATARS).updateValue(bytesReceived); - break; - case PACKET_TYPE_AVATAR_URLS: - processAvatarURLsMessage(app->_incomingPacket, bytesReceived); - break; - case PACKET_TYPE_AVATAR_FACE_VIDEO: - processAvatarFaceVideoMessage(app->_incomingPacket, bytesReceived); - break; - case PACKET_TYPE_DATA_SERVER_GET: - case PACKET_TYPE_DATA_SERVER_PUT: - case PACKET_TYPE_DATA_SERVER_SEND: - case PACKET_TYPE_DATA_SERVER_CONFIRM: - DataServerClient::processMessageFromDataServer(app->_incomingPacket, bytesReceived); - break; - default: - NodeList::getInstance()->processNodeData(senderSockAddr, app->_incomingPacket, bytesReceived); - break; + + // add this packet to our list of voxel packets and process them on the voxel processing + _voxelProcessor.queueReceivedPacket(senderSockAddr, _incomingPacket, bytesReceived); + break; } + case PACKET_TYPE_METAVOXEL_DATA: + _metavoxels.processData(QByteArray((const char*) _incomingPacket, bytesReceived), + senderSockAddr); + break; + case PACKET_TYPE_BULK_AVATAR_DATA: + NodeList::getInstance()->processBulkNodeData(senderSockAddr, + _incomingPacket, + bytesReceived); + getInstance()->_bandwidthMeter.inputStream(BandwidthMeter::AVATARS).updateValue(bytesReceived); + break; + case PACKET_TYPE_AVATAR_URLS: + processAvatarURLsMessage(_incomingPacket, bytesReceived); + break; + case PACKET_TYPE_AVATAR_FACE_VIDEO: + processAvatarFaceVideoMessage(_incomingPacket, bytesReceived); + break; + case PACKET_TYPE_DATA_SERVER_GET: + case PACKET_TYPE_DATA_SERVER_PUT: + case PACKET_TYPE_DATA_SERVER_SEND: + case PACKET_TYPE_DATA_SERVER_CONFIRM: + DataServerClient::processMessageFromDataServer(_incomingPacket, bytesReceived); + break; + default: + NodeList::getInstance()->processNodeData(senderSockAddr, _incomingPacket, bytesReceived); + break; } - } else if (!app->_enableNetworkThread) { - break; } } - - if (app->_enableNetworkThread) { - pthread_exit(0); - } - return NULL; } void Application::packetSentNotification(ssize_t length) { diff --git a/interface/src/Application.h b/interface/src/Application.h index a0bf608e98..8aa4f40f7f 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -215,6 +215,8 @@ public: public slots: void nodeKilled(SharedNodePointer node); + void processDatagrams(); + void sendAvatarFaceVideoMessage(int frameCount, const QByteArray& data); void exportVoxels(); void importVoxels(); @@ -467,10 +469,6 @@ private: Audio _audio; #endif - bool _enableNetworkThread; - pthread_t _networkReceiveThread; - bool _stopNetworkReceiveThread; - bool _enableProcessVoxelsThread; VoxelPacketProcessor _voxelProcessor; VoxelHideShowThread _voxelHideShowThread; diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 9d47806f18..ef295da7a8 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -786,7 +786,7 @@ SharedNodePointer NodeList::soloNodeOfType(char nodeType) { } } - return SharedNodePointer(NULL); + return SharedNodePointer(); } void NodeList::removeSilentNodes() { From cbcdeb570b937b0822e8c47239389d2dbd9648fc Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 14 Jan 2014 10:01:11 -0800 Subject: [PATCH 14/29] pull all available datagrams in Application processDatagrams --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7b82bc8d25..d3d49497d2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4263,7 +4263,7 @@ void Application::processDatagrams() { HifiSockAddr senderSockAddr; ssize_t bytesReceived; - if (NodeList::getInstance()->getNodeSocket().hasPendingDatagrams() && + while (NodeList::getInstance()->getNodeSocket().hasPendingDatagrams() && (bytesReceived = NodeList::getInstance()->getNodeSocket().readDatagram((char*) _incomingPacket, MAX_PACKET_SIZE, senderSockAddr.getAddressPointer(), From 53d435006c3f696a31027a6e552a7563532a79ac Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 14 Jan 2014 10:07:26 -0800 Subject: [PATCH 15/29] more follow mode cleanup, fix silent node iterator --- interface/src/Application.cpp | 5 ----- interface/src/Application.h | 2 -- libraries/shared/src/NodeList.cpp | 2 ++ 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d3d49497d2..35b61ae95c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -274,7 +274,6 @@ Application::~Application() { delete _logger; delete _settings; - delete _followMode; delete _glWidget; } @@ -1913,10 +1912,6 @@ void Application::init() { _glWidget->width(), _glWidget->height()); - _followMode = new QAction(this); - connect(_followMode, SIGNAL(triggered()), this, SLOT(toggleFollowMode())); - _pieMenu.addAction(_followMode); - _audio.init(_glWidget); _rearMirrorTools = new RearMirrorTools(_glWidget, _mirrorViewRect, _settings); diff --git a/interface/src/Application.h b/interface/src/Application.h index 8aa4f40f7f..98ba60cc5d 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -335,8 +335,6 @@ private: QMainWindow* _window; QGLWidget* _glWidget; - QAction* _followMode; - BandwidthMeter _bandwidthMeter; SerialInterface _serialHeadSensor; diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index ef295da7a8..91afb66db0 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -807,6 +807,8 @@ void NodeList::removeSilentNodes() { // unlock the node node->unlock(); + + nodeItem++; } } From 57f977668f46653c9c1cc485d41c3d0e76ea8451 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 14 Jan 2014 10:15:31 -0800 Subject: [PATCH 16/29] replace the Node mutex with a QMutex --- interface/src/Application.cpp | 7 ++----- libraries/octree-server/src/OctreeSendThread.cpp | 4 ++-- libraries/shared/src/Node.cpp | 7 +++---- libraries/shared/src/Node.h | 14 +++----------- libraries/shared/src/NodeList.cpp | 14 +++----------- 5 files changed, 13 insertions(+), 33 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 35b61ae95c..ac6ddf2a2b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2030,7 +2030,7 @@ void Application::updateAvatars(float deltaTime, glm::vec3 mouseRayOrigin, glm:: PerformanceWarning warn(showWarnings, "Application::updateAvatars()"); foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) { - node->lock(); + QMutexLocker(&node->getMutex()); if (node->getLinkedData()) { Avatar *avatar = (Avatar *)node->getLinkedData(); if (!avatar->isInitialized()) { @@ -2039,7 +2039,6 @@ void Application::updateAvatars(float deltaTime, glm::vec3 mouseRayOrigin, glm:: avatar->simulate(deltaTime, NULL); avatar->setMouseRay(mouseRayOrigin, mouseRayDirection); } - node->unlock(); } // simulate avatar fades @@ -3759,7 +3758,7 @@ void Application::renderAvatars(bool forceRenderHead, bool selfAvatarOnly) { NodeList* nodeList = NodeList::getInstance(); foreach(SharedNodePointer node, nodeList->getNodeHash()) { - node->lock(); + QMutexLocker(&node->getMutex()); if (node->getLinkedData() != NULL && node->getType() == NODE_TYPE_AGENT) { Avatar *avatar = (Avatar *)node->getLinkedData(); @@ -3769,8 +3768,6 @@ void Application::renderAvatars(bool forceRenderHead, bool selfAvatarOnly) { avatar->render(false); avatar->setDisplayingLookatVectors(Menu::getInstance()->isOptionChecked(MenuOption::LookAtVectors)); } - - node->unlock(); } // render avatar fades diff --git a/libraries/octree-server/src/OctreeSendThread.cpp b/libraries/octree-server/src/OctreeSendThread.cpp index 41450022d2..f8a3b77aa3 100644 --- a/libraries/octree-server/src/OctreeSendThread.cpp +++ b/libraries/octree-server/src/OctreeSendThread.cpp @@ -34,7 +34,7 @@ bool OctreeSendThread::process() { if (node) { // make sure the node list doesn't kill our node while we're using it - if (node->trylock()) { + if (node->getMutex().tryLock()) { gotLock = true; OctreeQueryNode* nodeData = NULL; @@ -51,7 +51,7 @@ bool OctreeSendThread::process() { packetsSent = packetDistributor(node.data(), nodeData, viewFrustumChanged); } - node->unlock(); // we're done with this node for now. + node->getMutex().unlock(); // we're done with this node for now. } } } else { diff --git a/libraries/shared/src/Node.cpp b/libraries/shared/src/Node.cpp index 36ee1682a6..2b815d57aa 100644 --- a/libraries/shared/src/Node.cpp +++ b/libraries/shared/src/Node.cpp @@ -33,9 +33,10 @@ Node::Node(const QUuid& uuid, char type, const HifiSockAddr& publicSocket, const _bytesReceivedMovingAverage(NULL), _linkedData(NULL), _isAlive(true), - _clockSkewUsec(0) + _clockSkewUsec(0), + _mutex() { - pthread_mutex_init(&_mutex, 0); + } Node::~Node() { @@ -46,8 +47,6 @@ Node::~Node() { } delete _bytesReceivedMovingAverage; - - pthread_mutex_destroy(&_mutex); } // Names of Node Types diff --git a/libraries/shared/src/Node.h b/libraries/shared/src/Node.h index fe6e95dac8..c5cfa61046 100644 --- a/libraries/shared/src/Node.h +++ b/libraries/shared/src/Node.h @@ -19,6 +19,7 @@ #endif #include +#include #include #include "HifiSockAddr.h" @@ -73,13 +74,7 @@ public: int getClockSkewUsec() const { return _clockSkewUsec; } void setClockSkewUsec(int clockSkew) { _clockSkewUsec = clockSkew; } - void lock() { pthread_mutex_lock(&_mutex); } - - /// returns false if lock failed, true if you got the lock - bool trylock() { return (pthread_mutex_trylock(&_mutex) == 0); } - void unlock() { pthread_mutex_unlock(&_mutex); } - - static void printLog(Node const&); + QMutex& getMutex() { return _mutex; } private: // privatize copy and assignment operator to disallow Node copying @@ -98,12 +93,9 @@ private: bool _isAlive; int _pingMs; int _clockSkewUsec; - pthread_mutex_t _mutex; + QMutex _mutex; }; -int unpackNodeId(unsigned char *packedData, uint16_t *nodeId); -int packNodeId(unsigned char *packStore, uint16_t nodeId); - QDebug operator<<(QDebug debug, const Node &message); #endif /* defined(__hifi__Node__) */ diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 91afb66db0..c3b8fdebc6 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -227,7 +227,7 @@ void NodeList::processBulkNodeData(const HifiSockAddr& senderAddress, unsigned c } int NodeList::updateNodeWithData(Node *node, const HifiSockAddr& senderSockAddr, unsigned char *packetData, int dataBytes) { - node->lock(); + QMutexLocker(&node->getMutex()); node->setLastHeardMicrostamp(usecTimestampNow()); @@ -244,12 +244,9 @@ int NodeList::updateNodeWithData(Node *node, const HifiSockAddr& senderSockAddr, int numParsedBytes = node->getLinkedData()->parseData(packetData, dataBytes); - node->unlock(); - return numParsedBytes; } else { // we weren't able to match the sender address to the address we have for this node, unlock and don't parse - node->unlock(); return 0; } } @@ -695,7 +692,7 @@ SharedNodePointer NodeList::addOrUpdateNode(const QUuid& uuid, char nodeType, return newNodeSharedPointer; } else { SharedNodePointer node = matchingNodeItem.value(); - matchingNodeItem.value()->lock(); + QMutexLocker(&node->getMutex()); if (node->getType() == NODE_TYPE_AUDIO_MIXER || node->getType() == NODE_TYPE_VOXEL_SERVER || @@ -716,8 +713,6 @@ SharedNodePointer NodeList::addOrUpdateNode(const QUuid& uuid, char nodeType, qDebug() << "Local socket change for node" << *node << "\n"; } - node->unlock(); - // we had this node already, do nothing for now return node; } @@ -797,7 +792,7 @@ void NodeList::removeSilentNodes() { SharedNodePointer node = nodeItem.value(); - node->lock(); + QMutexLocker(&node->getMutex()); if ((usecTimestampNow() - node->getLastHeardMicrostamp()) > NODE_SILENCE_THRESHOLD_USECS) { @@ -805,9 +800,6 @@ void NodeList::removeSilentNodes() { _nodeHash.erase(nodeItem); } - // unlock the node - node->unlock(); - nodeItem++; } } From ed0ed96029c870a4fa2c00b161f754449d0e770b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 14 Jan 2014 10:28:41 -0800 Subject: [PATCH 17/29] properly emit signal on silent node removal --- domain-server/src/DomainServer.cpp | 4 ++-- domain-server/src/DomainServer.h | 2 +- libraries/octree-server/src/OctreeServer.h | 1 + libraries/shared/src/NodeList.cpp | 26 +++++++++++----------- libraries/shared/src/NodeList.h | 2 ++ 5 files changed, 19 insertions(+), 16 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 4d47aa3885..b5abd3d003 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -77,7 +77,7 @@ DomainServer::DomainServer(int argc, char* argv[]) : // Start the web server. mg_start(&callbacks, NULL, options); - connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), SLOT(nodeKilled(SharedNodePointer))); + connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), this, SLOT(nodeKilled(SharedNodePointer))); if (!_staticAssignmentFile.exists() || _voxelServerConfig) { @@ -492,7 +492,7 @@ void DomainServer::addReleasedAssignmentBackToQueue(Assignment* releasedAssignme } } -void DomainServer::nodeKilled(Node* node) { +void DomainServer::nodeKilled(SharedNodePointer node) { // if this node has linked data it was from an assignment if (node->getLinkedData()) { Assignment* nodeAssignment = (Assignment*) node->getLinkedData(); diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 99bd560228..40cebdfa3f 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -33,7 +33,7 @@ public: public slots: /// Called by NodeList to inform us that a node has been killed. - void nodeKilled(Node* node); + void nodeKilled(SharedNodePointer node); private: static int civetwebRequestHandler(struct mg_connection *connection); diff --git a/libraries/octree-server/src/OctreeServer.h b/libraries/octree-server/src/OctreeServer.h index f6380788a6..38ac602d9b 100644 --- a/libraries/octree-server/src/OctreeServer.h +++ b/libraries/octree-server/src/OctreeServer.h @@ -24,6 +24,7 @@ /// Handles assignments of type OctreeServer - sending octrees to various clients. class OctreeServer : public ThreadedAssignment { + Q_OBJECT public: OctreeServer(const unsigned char* dataBuffer, int numBytes); ~OctreeServer(); diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index c3b8fdebc6..6ca87fa4db 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -442,13 +442,18 @@ void NodeList::processSTUNResponse(unsigned char* packetData, size_t dataBytes) } void NodeList::killNodeWithUUID(const QUuid& nodeUUID) { - NodeHash::iterator nodeToKill = _nodeHash.find(nodeUUID); - if (nodeToKill != _nodeHash.end()) { - emit nodeKilled(nodeToKill.value()); - _nodeHash.erase(nodeToKill); + NodeHash::iterator nodeItemToKill = _nodeHash.find(nodeUUID); + if (nodeItemToKill != _nodeHash.end()) { + killNodeAtHashIterator(nodeItemToKill); } } +void NodeList::killNodeAtHashIterator(NodeHash::iterator nodeItemToKill) { + emit nodeKilled(nodeItemToKill.value()); + _nodeHash.erase(nodeItemToKill); +} + + void NodeList::sendKillNode(const char* nodeTypes, int numNodeTypes) { unsigned char packet[MAX_PACKET_SIZE]; unsigned char* packetPosition = packet; @@ -474,12 +479,8 @@ void NodeList::processKillNode(unsigned char* packetData, size_t dataBytes) { packetData += NUM_BYTES_RFC4122_UUID; dataBytes -= NUM_BYTES_RFC4122_UUID; - // make sure the node exists - NodeHash::iterator nodeToKill = _nodeHash.find(nodeUUID); - if (nodeToKill != _nodeHash.end()) { - emit nodeKilled(nodeToKill.value()); - _nodeHash.erase(nodeToKill); - } + // kill the node with this UUID, if it exists + killNodeWithUUID(nodeUUID); } void NodeList::sendDomainServerCheckIn() { @@ -795,9 +796,8 @@ void NodeList::removeSilentNodes() { QMutexLocker(&node->getMutex()); if ((usecTimestampNow() - node->getLastHeardMicrostamp()) > NODE_SILENCE_THRESHOLD_USECS) { - - // kill this node, don't lock - we already did it - _nodeHash.erase(nodeItem); + // call our private method to kill this node (removes it and emits the right signal) + killNodeAtHashIterator(nodeItem); } nodeItem++; diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index efb08f32d1..44fa4232db 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -144,6 +144,8 @@ private: void processKillNode(unsigned char* packetData, size_t dataBytes); + void killNodeAtHashIterator(NodeHash::iterator nodeItemToKill); + NodeHash _nodeHash; QString _domainHostname; HifiSockAddr _domainSockAddr; From 66f50c38e303d78c26cf9420944bfed54c05e62c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 14 Jan 2014 10:48:47 -0800 Subject: [PATCH 18/29] repair iterator push on silent node removal --- libraries/shared/src/NodeList.cpp | 21 ++++++++++++--------- libraries/shared/src/NodeList.h | 2 +- libraries/shared/src/PacketHeaders.cpp | 2 +- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 6ca87fa4db..a6411c7937 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -279,10 +279,8 @@ void NodeList::clear() { // iterate the nodes in the list while (nodeItem != _nodeHash.end()) { - // emit our signal to say this node has been killed - emit nodeKilled(nodeItem.value()); - // erase the node from our node hash - _nodeHash.erase(nodeItem); + killNodeAtHashIterator(nodeItem); + nodeItem++; } } @@ -448,9 +446,11 @@ void NodeList::killNodeWithUUID(const QUuid& nodeUUID) { } } -void NodeList::killNodeAtHashIterator(NodeHash::iterator nodeItemToKill) { +NodeHash::iterator NodeList::killNodeAtHashIterator(NodeHash::iterator& nodeItemToKill) { + qDebug() << "Killed" << *nodeItemToKill.value() << "\n"; emit nodeKilled(nodeItemToKill.value()); - _nodeHash.erase(nodeItemToKill); + + return _nodeHash.erase(nodeItemToKill); } @@ -789,6 +789,8 @@ void NodeList::removeSilentNodes() { NodeHash::iterator nodeItem = _nodeHash.begin(); + int index = 0; + while (nodeItem != _nodeHash.end()) { SharedNodePointer node = nodeItem.value(); @@ -797,10 +799,11 @@ void NodeList::removeSilentNodes() { if ((usecTimestampNow() - node->getLastHeardMicrostamp()) > NODE_SILENCE_THRESHOLD_USECS) { // call our private method to kill this node (removes it and emits the right signal) - killNodeAtHashIterator(nodeItem); + nodeItem = killNodeAtHashIterator(nodeItem); + } else { + // we didn't kill this node, push the iterator forwards + ++nodeItem; } - - nodeItem++; } } diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index 44fa4232db..21ed3533af 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -144,7 +144,7 @@ private: void processKillNode(unsigned char* packetData, size_t dataBytes); - void killNodeAtHashIterator(NodeHash::iterator nodeItemToKill); + NodeHash::iterator killNodeAtHashIterator(NodeHash::iterator& nodeItemToKill); NodeHash _nodeHash; QString _domainHostname; diff --git a/libraries/shared/src/PacketHeaders.cpp b/libraries/shared/src/PacketHeaders.cpp index ec5e8ee692..2ed6608592 100644 --- a/libraries/shared/src/PacketHeaders.cpp +++ b/libraries/shared/src/PacketHeaders.cpp @@ -20,7 +20,7 @@ PACKET_VERSION versionForPacketType(PACKET_TYPE type) { return 2; case PACKET_TYPE_HEAD_DATA: - return 12; + return 13; case PACKET_TYPE_AVATAR_URLS: return 2; From 9efb391ecf4a1e00531093d71383b507190085b4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 14 Jan 2014 10:49:46 -0800 Subject: [PATCH 19/29] repair crazy references to node ponter from old iterator style --- assignment-client/src/audio/AudioMixer.cpp | 2 +- assignment-client/src/avatars/AvatarMixer.cpp | 2 +- domain-server/src/DomainServer.cpp | 4 ++-- interface/src/ui/VoxelStatsDialog.cpp | 2 +- libraries/octree/src/JurisdictionListener.cpp | 2 +- libraries/octree/src/OctreeEditPacketSender.cpp | 4 ++-- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index d15f7172ae..0524576474 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -272,7 +272,7 @@ void AudioMixer::run() { foreach(SharedNodePointer node, nodeList->getNodeHash()) { if (node->getType() == NODE_TYPE_AGENT && node->getActiveSocket() && node->getLinkedData() && ((AudioMixerClientData*) node->getLinkedData())->getAvatarAudioRingBuffer()) { - prepareMixForListeningNode(&(*node)); + prepareMixForListeningNode(node.data()); memcpy(clientPacket + numBytesPacketHeader, _clientSamples, sizeof(_clientSamples)); nodeList->getNodeSocket().writeDatagram((char*) clientPacket, sizeof(clientPacket), diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index b614e7ac2b..67685cf085 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -80,7 +80,7 @@ void broadcastAvatarData() { if (otherNode->getLinkedData() && otherNode->getUUID() != node->getUUID()) { unsigned char* avatarDataEndpoint = addNodeToBroadcastPacket((unsigned char*)&avatarDataBuffer[0], - &*otherNode); + otherNode.data()); int avatarDataLength = avatarDataEndpoint - (unsigned char*)&avatarDataBuffer; if (avatarDataLength + packetLength <= MAX_PACKET_SIZE) { diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index b5abd3d003..6fe2aff926 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -207,7 +207,7 @@ void DomainServer::readAvailableDatagrams() { // don't send avatar nodes to other avatars, that will come from avatar mixer if (nodeType != NODE_TYPE_AGENT || node->getType() != NODE_TYPE_AGENT) { - currentBufferPos = addNodeToBroadcastPacket(currentBufferPos, &(*node)); + currentBufferPos = addNodeToBroadcastPacket(currentBufferPos, node.data()); } } @@ -322,7 +322,7 @@ int DomainServer::civetwebRequestHandler(struct mg_connection *connection) { if (node->getLinkedData()) { // add the node using the UUID as the key QString uuidString = uuidStringWithoutCurlyBraces(node->getUUID()); - assignedNodesJSON[uuidString] = jsonObjectForNode(&(*node)); + assignedNodesJSON[uuidString] = jsonObjectForNode(node.data()); } } diff --git a/interface/src/ui/VoxelStatsDialog.cpp b/interface/src/ui/VoxelStatsDialog.cpp index a25fe9f097..e154e30c74 100644 --- a/interface/src/ui/VoxelStatsDialog.cpp +++ b/interface/src/ui/VoxelStatsDialog.cpp @@ -263,7 +263,7 @@ void VoxelStatsDialog::showOctreeServersOfType(int& serverCount, NODE_TYPE serve std::stringstream extraDetails(""); std::stringstream linkDetails(""); - if (nodeList->getNodeActiveSocketOrPing(&(*node))) { + if (nodeList->getNodeActiveSocketOrPing(node.data())) { serverDetails << "active "; } else { serverDetails << "inactive "; diff --git a/libraries/octree/src/JurisdictionListener.cpp b/libraries/octree/src/JurisdictionListener.cpp index 29f6dde309..60a3eddd57 100644 --- a/libraries/octree/src/JurisdictionListener.cpp +++ b/libraries/octree/src/JurisdictionListener.cpp @@ -45,7 +45,7 @@ bool JurisdictionListener::queueJurisdictionRequest() { NodeList* nodeList = NodeList::getInstance(); foreach(SharedNodePointer node, nodeList->getNodeHash()) { - if (nodeList->getNodeActiveSocketOrPing(&(*node)) && + if (nodeList->getNodeActiveSocketOrPing(node.data()) && node->getType() == getNodeType()) { const HifiSockAddr* nodeAddress = node->getActiveSocket(); PacketSender::queuePacketForSending(*nodeAddress, bufferOut, sizeOut); diff --git a/libraries/octree/src/OctreeEditPacketSender.cpp b/libraries/octree/src/OctreeEditPacketSender.cpp index 1367ca41bd..b7a31f166b 100644 --- a/libraries/octree/src/OctreeEditPacketSender.cpp +++ b/libraries/octree/src/OctreeEditPacketSender.cpp @@ -61,7 +61,7 @@ bool OctreeEditPacketSender::serversExist() const { foreach(SharedNodePointer node, nodeList->getNodeHash()) { // only send to the NodeTypes that are getMyNodeType() if (node->getType() == getMyNodeType()) { - if (nodeList->getNodeActiveSocketOrPing(&(*node))) { + if (nodeList->getNodeActiveSocketOrPing(node.data())) { QUuid nodeUUID = node->getUUID(); // If we've got Jurisdictions set, then check to see if we know the jurisdiction for this server if (_serverJurisdictions) { @@ -91,7 +91,7 @@ void OctreeEditPacketSender::queuePacketToNode(const QUuid& nodeUUID, unsigned c // only send to the NodeTypes that are getMyNodeType() if (node->getType() == getMyNodeType() && ((node->getUUID() == nodeUUID) || (nodeUUID.isNull()))) { - if (nodeList->getNodeActiveSocketOrPing(&(*node))) { + if (nodeList->getNodeActiveSocketOrPing(node.data())) { const HifiSockAddr* nodeAddress = node->getActiveSocket(); queuePacketForSending(*nodeAddress, buffer, length); From 718d04bd718aa6d786f5f7c62c148f63b9d261e8 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 14 Jan 2014 10:53:17 -0800 Subject: [PATCH 20/29] correct iterator push on NodeList clear --- libraries/shared/src/NodeList.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index a6411c7937..81b1301a97 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -279,8 +279,7 @@ void NodeList::clear() { // iterate the nodes in the list while (nodeItem != _nodeHash.end()) { - killNodeAtHashIterator(nodeItem); - nodeItem++; + nodeItem = killNodeAtHashIterator(nodeItem); } } From 5a43c2c66b45d194bb7507588c3b7e93cab8e5dc Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 14 Jan 2014 10:53:53 -0800 Subject: [PATCH 21/29] remove extraneous node destructor debug --- libraries/shared/src/Node.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/shared/src/Node.cpp b/libraries/shared/src/Node.cpp index 2b815d57aa..8a0f5e3014 100644 --- a/libraries/shared/src/Node.cpp +++ b/libraries/shared/src/Node.cpp @@ -39,9 +39,7 @@ Node::Node(const QUuid& uuid, char type, const HifiSockAddr& publicSocket, const } -Node::~Node() { - qDebug() << "Destructor for node with UUID" << _uuid << "called.\n"; - +Node::~Node() { if (_linkedData) { _linkedData->deleteOrDeleteLater(); } From 9de098b4d90a90ed7c0be833d77148d16544bc37 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 14 Jan 2014 10:55:18 -0800 Subject: [PATCH 22/29] fix logging name for metavoxel server --- assignment-client/src/metavoxels/MetavoxelServer.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/assignment-client/src/metavoxels/MetavoxelServer.cpp b/assignment-client/src/metavoxels/MetavoxelServer.cpp index fc586599ce..65c36b77b3 100644 --- a/assignment-client/src/metavoxels/MetavoxelServer.cpp +++ b/assignment-client/src/metavoxels/MetavoxelServer.cpp @@ -29,8 +29,10 @@ void MetavoxelServer::removeSession(const QUuid& sessionId) { delete _sessions.take(sessionId); } +const char METAVOXEL_SERVER_LOGGING_NAME[] = "avatar-mixer"; + void MetavoxelServer::run() { - commonInit("metavoxel-server", NODE_TYPE_METAVOXEL_SERVER); + commonInit(METAVOXEL_SERVER_LOGGING_NAME, NODE_TYPE_METAVOXEL_SERVER); _lastSend = QDateTime::currentMSecsSinceEpoch(); _sendTimer.start(SEND_INTERVAL); From e888366fd8aad9dc3de82dfcdba38790f43498b9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 14 Jan 2014 10:57:34 -0800 Subject: [PATCH 23/29] remove unused index variable --- libraries/shared/src/NodeList.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 81b1301a97..12437525a5 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -788,8 +788,6 @@ void NodeList::removeSilentNodes() { NodeHash::iterator nodeItem = _nodeHash.begin(); - int index = 0; - while (nodeItem != _nodeHash.end()) { SharedNodePointer node = nodeItem.value(); From fa01383f3f0c4be1a9f9fccb0407c19bec7fe299 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 14 Jan 2014 11:26:26 -0800 Subject: [PATCH 24/29] move the NodeList to the thread used for a ThreadedAssignment --- assignment-client/src/AssignmentClient.cpp | 6 ++++++ libraries/shared/src/Node.cpp | 2 +- libraries/shared/src/NodeList.cpp | 1 - libraries/shared/src/ThreadedAssignment.cpp | 6 +++--- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index f3458c8afb..935eecc510 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -148,6 +148,9 @@ void AssignmentClient::readPendingDatagrams() { _currentAssignment->moveToThread(workerThread); + // move the NodeList to the thread used for the _current assignment + nodeList->moveToThread(workerThread); + // Starts an event loop, and emits workerThread->started() workerThread->start(); } else { @@ -172,6 +175,9 @@ void AssignmentClient::assignmentCompleted() { NodeList* nodeList = NodeList::getInstance(); + // move the NodeList back to our thread + nodeList->moveToThread(thread()); + // reset our NodeList by switching back to unassigned and clearing the list nodeList->setOwnerType(NODE_TYPE_UNASSIGNED); nodeList->reset(); diff --git a/libraries/shared/src/Node.cpp b/libraries/shared/src/Node.cpp index 8a0f5e3014..057cf6a7d7 100644 --- a/libraries/shared/src/Node.cpp +++ b/libraries/shared/src/Node.cpp @@ -39,7 +39,7 @@ Node::Node(const QUuid& uuid, char type, const HifiSockAddr& publicSocket, const } -Node::~Node() { +Node::~Node() { if (_linkedData) { _linkedData->deleteOrDeleteLater(); } diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 12437525a5..b95efb550b 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -789,7 +789,6 @@ void NodeList::removeSilentNodes() { NodeHash::iterator nodeItem = _nodeHash.begin(); while (nodeItem != _nodeHash.end()) { - SharedNodePointer node = nodeItem.value(); QMutexLocker(&node->getMutex()); diff --git a/libraries/shared/src/ThreadedAssignment.cpp b/libraries/shared/src/ThreadedAssignment.cpp index b16c180c9d..8411c26fc6 100644 --- a/libraries/shared/src/ThreadedAssignment.cpp +++ b/libraries/shared/src/ThreadedAssignment.cpp @@ -41,9 +41,9 @@ void ThreadedAssignment::commonInit(const char* targetName, NODE_TYPE nodeType) connect(pingNodesTimer, SIGNAL(timeout()), nodeList, SLOT(pingInactiveNodes())); pingNodesTimer->start(PING_INACTIVE_NODE_INTERVAL_USECS / 1000); - QTimer* silentNodeTimer = new QTimer(this); - connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes())); - silentNodeTimer->start(NODE_SILENCE_THRESHOLD_USECS / 1000); + QTimer* silentNodeRemovalTimer = new QTimer(this); + connect(silentNodeRemovalTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes())); + silentNodeRemovalTimer->start(NODE_SILENCE_THRESHOLD_USECS / 1000); } void ThreadedAssignment::checkInWithDomainServerOrExit() { From bdc31a3b480e72f9f8d5b4853e0b30a03ca1b804 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 14 Jan 2014 11:38:05 -0800 Subject: [PATCH 25/29] replace the DomainChangeListener class with a signal/slot combo --- interface/src/Application.cpp | 10 +++++----- interface/src/Application.h | 6 +++--- libraries/shared/src/NodeList.cpp | 25 ++----------------------- libraries/shared/src/NodeList.h | 12 ++---------- 4 files changed, 12 insertions(+), 41 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5a6aec5fe8..ddec0554f8 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -176,7 +176,8 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : nodeList->addHook(&_voxels); nodeList->addHook(this); - nodeList->addDomainListener(this); + + connect(nodeList, SIGNAL(domainChanged(const QString&)), SLOT(domainChanged(const QString&))); // network receive thread and voxel parsing thread are both controlled by the --nonblocking command line _enableProcessVoxelsThread = _enableNetworkThread = !cmdOptionExists(argc, constArgv, "--nonblocking"); @@ -265,7 +266,6 @@ Application::~Application() { storeSizeAndPosition(); NodeList::getInstance()->removeHook(&_voxels); NodeList::getInstance()->removeHook(this); - NodeList::getInstance()->removeDomainListener(this); _sharedVoxelSystem.changeTree(new VoxelTree); @@ -4184,9 +4184,9 @@ void Application::updateWindowTitle(){ _window->setWindowTitle(title); } -void Application::domainChanged(QString domain) { +void Application::domainChanged(const QString& domainHostname) { // update the user's last domain in their Profile (which will propagate to data-server) - _profile.updateDomain(domain); + _profile.updateDomain(domainHostname); updateWindowTitle(); @@ -4199,7 +4199,7 @@ void Application::domainChanged(QString domain) { _particleServerJurisdictions.clear(); // reset our persist thread - qDebug() << "domainChanged()... domain=" << domain << " swapping persist cache\n"; + qDebug() << "domainChanged()... domain=" << domainHostname << " swapping persist cache\n"; updateLocalOctreeCache(); } diff --git a/interface/src/Application.h b/interface/src/Application.h index 1da7de0224..876454d396 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -95,7 +95,7 @@ static const float NODE_KILLED_RED = 1.0f; static const float NODE_KILLED_GREEN = 0.0f; static const float NODE_KILLED_BLUE = 0.0f; -class Application : public QApplication, public NodeListHook, public PacketSenderNotify, public DomainChangeListener { +class Application : public QApplication, public NodeListHook, public PacketSenderNotify { Q_OBJECT friend class VoxelPacketProcessor; @@ -198,8 +198,6 @@ public: virtual void nodeKilled(Node* node); virtual void packetSentNotification(ssize_t length); - virtual void domainChanged(QString domain); - VoxelShader& getVoxelShader() { return _voxelShader; } PointShader& getPointShader() { return _pointShader; } FileLogger* getLogger() { return _logger; } @@ -214,6 +212,8 @@ public: void setIsHighlightVoxel(bool isHighlightVoxel) { _isHighlightVoxel = isHighlightVoxel; } public slots: + void domainChanged(const QString& domainHostname); + void sendAvatarFaceVideoMessage(int frameCount, const QByteArray& data); void exportVoxels(); void importVoxels(); diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 0a50a659b2..8df4b6008f 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -103,7 +103,7 @@ void NodeList::setDomainHostname(const QString& domainHostname) { // reset our _domainIP to the null address so that a lookup happens on next check in _domainSockAddr.setAddress(QHostAddress::Null); - notifyDomainChanged(); + emit domainChanged(_domainHostname); } } @@ -848,7 +848,7 @@ void NodeList::loadData(QSettings *settings) { if (domainServerHostname.size() > 0) { _domainHostname = domainServerHostname; - notifyDomainChanged(); + emit domainChanged(_domainHostname); } settings->endGroup(); @@ -942,21 +942,6 @@ void NodeListIterator::skipDeadAndStopIncrement() { } } -void NodeList::addDomainListener(DomainChangeListener* listener) { - _domainListeners.push_back(listener); - QString domain = _domainHostname.isEmpty() ? _domainSockAddr.getAddress().toString() : _domainHostname; - listener->domainChanged(domain); -} - -void NodeList::removeDomainListener(DomainChangeListener* listener) { - for (int i = 0; i < _domainListeners.size(); i++) { - if (_domainListeners[i] == listener) { - _domainListeners.erase(_domainListeners.begin() + i); - return; - } - } -} - void NodeList::addHook(NodeListHook* hook) { _hooks.push_back(hook); } @@ -983,9 +968,3 @@ void NodeList::notifyHooksOfKilledNode(Node* node) { _hooks[i]->nodeKilled(node); } } - -void NodeList::notifyDomainChanged() { - for (int i = 0; i < _domainListeners.size(); i++) { - _domainListeners[i]->domainChanged(_domainHostname); - } -} diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index 47cdbac99d..62137f34f1 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -52,11 +52,6 @@ public: virtual void nodeKilled(Node* node) = 0; }; -class DomainChangeListener { -public: - virtual void domainChanged(QString domain) = 0; -}; - class NodeList : public QObject { Q_OBJECT public: @@ -134,14 +129,13 @@ public: void notifyHooksOfAddedNode(Node* node); void notifyHooksOfKilledNode(Node* node); - void addDomainListener(DomainChangeListener* listener); - void removeDomainListener(DomainChangeListener* listener); - const HifiSockAddr* getNodeActiveSocketOrPing(Node* node); public slots: void sendDomainServerCheckIn(); void pingInactiveNodes(); void removeSilentNodes(); +signals: + void domainChanged(const QString& domainHostname); private: static NodeList* _sharedInstance; @@ -175,10 +169,8 @@ private: void timePingReply(const HifiSockAddr& nodeAddress, unsigned char *packetData); std::vector _hooks; - std::vector _domainListeners; void resetDomainData(char domainField[], const char* domainData); - void notifyDomainChanged(); void domainLookup(); }; From bcf9e04f563c944cd8bb9a1d7e8d2d79e236fb9e Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 14 Jan 2014 14:34:00 -0800 Subject: [PATCH 26/29] only output first starve for a PositionalAudioRingBuffer --- libraries/audio/src/PositionalAudioRingBuffer.cpp | 13 +++++++++++-- libraries/audio/src/PositionalAudioRingBuffer.h | 1 + 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/libraries/audio/src/PositionalAudioRingBuffer.cpp b/libraries/audio/src/PositionalAudioRingBuffer.cpp index 7037eb2154..c7084e0d1d 100644 --- a/libraries/audio/src/PositionalAudioRingBuffer.cpp +++ b/libraries/audio/src/PositionalAudioRingBuffer.cpp @@ -20,7 +20,8 @@ PositionalAudioRingBuffer::PositionalAudioRingBuffer(PositionalAudioRingBuffer:: _position(0.0f, 0.0f, 0.0f), _orientation(0.0f, 0.0f, 0.0f, 0.0f), _willBeAddedToMix(false), - _shouldLoopbackForNode(false) + _shouldLoopbackForNode(false), + _shouldOutputStarveDebug(true) { } @@ -57,11 +58,19 @@ int PositionalAudioRingBuffer::parsePositionalData(unsigned char* sourceBuffer, bool PositionalAudioRingBuffer::shouldBeAddedToMix(int numJitterBufferSamples) { if (!isNotStarvedOrHasMinimumSamples(NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL + numJitterBufferSamples)) { - qDebug() << "Starved and do not have minimum samples to start. Buffer held back.\n"; + if (_shouldOutputStarveDebug) { + qDebug() << "Starved and do not have minimum samples to start. Buffer held back.\n"; + _shouldOutputStarveDebug = false; + } + return false; } else if (samplesAvailable() < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL) { qDebug() << "Do not have number of samples needed for interval. Buffer starved.\n"; _isStarved = true; + + // reset our _shouldOutputStarveDebug to true so the next is printed + _shouldOutputStarveDebug = true; + return false; } else { // good buffer, add this to the mix diff --git a/libraries/audio/src/PositionalAudioRingBuffer.h b/libraries/audio/src/PositionalAudioRingBuffer.h index 189ac34058..55ed627c4d 100644 --- a/libraries/audio/src/PositionalAudioRingBuffer.h +++ b/libraries/audio/src/PositionalAudioRingBuffer.h @@ -49,6 +49,7 @@ protected: glm::quat _orientation; bool _willBeAddedToMix; bool _shouldLoopbackForNode; + bool _shouldOutputStarveDebug; }; #endif /* defined(__hifi__PositionalAudioRingBuffer__) */ From 8676ac38f987f55fc25d777157ded98cc8d042c1 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 14 Jan 2014 15:54:09 -0800 Subject: [PATCH 27/29] foreach spacing and reference repairs --- assignment-client/src/audio/AudioMixer.cpp | 8 ++++---- assignment-client/src/avatars/AvatarMixer.cpp | 6 +++--- domain-server/src/DomainServer.cpp | 10 +++++----- interface/src/Application.cpp | 14 +++++++------- interface/src/DataServerClient.cpp | 4 ++-- interface/src/VoxelSystem.cpp | 2 +- interface/src/avatar/Hand.cpp | 2 +- interface/src/avatar/MyAvatar.cpp | 2 +- interface/src/ui/VoxelStatsDialog.cpp | 2 +- libraries/octree/src/JurisdictionListener.cpp | 2 +- libraries/octree/src/OctreeEditPacketSender.cpp | 8 ++++---- .../particles/src/ParticleCollisionSystem.cpp | 2 +- libraries/shared/src/NodeList.cpp | 12 ++++++------ 13 files changed, 37 insertions(+), 37 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 0524576474..37756679b0 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -188,7 +188,7 @@ void AudioMixer::prepareMixForListeningNode(Node* node) { memset(_clientSamples, 0, sizeof(_clientSamples)); // loop through all other nodes that have sufficient audio to mix - foreach(SharedNodePointer otherNode, NodeList::getInstance()->getNodeHash()) { + foreach (const SharedNodePointer& otherNode, NodeList::getInstance()->getNodeHash()) { if (otherNode->getLinkedData()) { AudioMixerClientData* otherNodeClientData = (AudioMixerClientData*) otherNode->getLinkedData(); @@ -263,13 +263,13 @@ void AudioMixer::run() { break; } - foreach(SharedNodePointer node, nodeList->getNodeHash()) { + foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { if (node->getLinkedData()) { ((AudioMixerClientData*) node->getLinkedData())->checkBuffersBeforeFrameSend(JITTER_BUFFER_SAMPLES); } } - foreach(SharedNodePointer node, nodeList->getNodeHash()) { + foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { if (node->getType() == NODE_TYPE_AGENT && node->getActiveSocket() && node->getLinkedData() && ((AudioMixerClientData*) node->getLinkedData())->getAvatarAudioRingBuffer()) { prepareMixForListeningNode(node.data()); @@ -282,7 +282,7 @@ void AudioMixer::run() { } // push forward the next output pointers for any audio buffers we used - foreach(SharedNodePointer node, nodeList->getNodeHash()) { + foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { if (node->getLinkedData()) { ((AudioMixerClientData*) node->getLinkedData())->pushBuffersAfterFrameSend(); } diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 67685cf085..b9aa911bf0 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -67,7 +67,7 @@ void broadcastAvatarData() { NodeList* nodeList = NodeList::getInstance(); - foreach(SharedNodePointer node, nodeList->getNodeHash()) { + foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { if (node->getLinkedData() && node->getType() == NODE_TYPE_AGENT && node->getActiveSocket()) { // reset packet pointers for this node @@ -76,7 +76,7 @@ void broadcastAvatarData() { // this is an AGENT we have received head data from // send back a packet with other active node data to this node - foreach(SharedNodePointer otherNode, nodeList->getNodeHash()) { + foreach (const SharedNodePointer& otherNode, nodeList->getNodeHash()) { if (otherNode->getLinkedData() && otherNode->getUUID() != node->getUUID()) { unsigned char* avatarDataEndpoint = addNodeToBroadcastPacket((unsigned char*)&avatarDataBuffer[0], @@ -142,7 +142,7 @@ void AvatarMixer::processDatagram(const QByteArray& dataByteArray, const HifiSoc QUuid nodeUUID = QUuid::fromRfc4122(dataByteArray.mid(numBytesForPacketHeader((unsigned char*) dataByteArray.data()), NUM_BYTES_RFC4122_UUID)); // let everyone else know about the update - foreach(SharedNodePointer node, nodeList->getNodeHash()) { + foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { if (node->getActiveSocket() && node->getUUID() != nodeUUID) { nodeList->getNodeSocket().writeDatagram(dataByteArray, node->getActiveSocket()->getAddress(), diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 6fe2aff926..a295a9c1c1 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -201,7 +201,7 @@ void DomainServer::readAvailableDatagrams() { if (numInterestTypes > 0) { // if the node has sent no types of interest, assume they want nothing but their own ID back - foreach(SharedNodePointer node, nodeList->getNodeHash()) { + foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { if (node->getUUID() != nodeUUID && memchr(nodeTypesOfInterest, node->getType(), numInterestTypes)) { @@ -318,7 +318,7 @@ int DomainServer::civetwebRequestHandler(struct mg_connection *connection) { QJsonObject assignedNodesJSON; // enumerate the NodeList to find the assigned nodes - foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) { + foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { if (node->getLinkedData()) { // add the node using the UUID as the key QString uuidString = uuidStringWithoutCurlyBraces(node->getUUID()); @@ -370,7 +370,7 @@ int DomainServer::civetwebRequestHandler(struct mg_connection *connection) { // enumerate the NodeList to find the assigned nodes NodeList* nodeList = NodeList::getInstance(); - foreach(SharedNodePointer node, nodeList->getNodeHash()) { + foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { // add the node using the UUID as the key QString uuidString = uuidStringWithoutCurlyBraces(node->getUUID()); nodesJSON[uuidString] = jsonObjectForNode(node.data()); @@ -735,7 +735,7 @@ bool DomainServer::checkInWithUUIDMatchesExistingNode(const HifiSockAddr& nodePu const QUuid& checkInUUID) { NodeList* nodeList = NodeList::getInstance(); - foreach(SharedNodePointer node, nodeList->getNodeHash()) { + foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { if (node->getLinkedData() && nodePublicSocket == node->getPublicSocket() && nodeLocalSocket == node->getLocalSocket() @@ -767,7 +767,7 @@ void DomainServer::addStaticAssignmentsBackToQueueAfterRestart() { NodeList* nodeList = NodeList::getInstance(); // enumerate the nodes and check if there is one with an attached assignment with matching UUID - foreach(SharedNodePointer node, nodeList->getNodeHash()) { + foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { if (node->getLinkedData()) { Assignment* linkedAssignment = (Assignment*) node->getLinkedData(); if (linkedAssignment->getUUID() == _staticAssignments[i].getUUID()) { diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ac6ddf2a2b..3a821677d6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1969,7 +1969,7 @@ void Application::updateLookatTargetAvatar(const glm::vec3& mouseRayOrigin, cons Avatar* Application::findLookatTargetAvatar(const glm::vec3& mouseRayOrigin, const glm::vec3& mouseRayDirection, glm::vec3& eyePosition, QUuid& nodeUUID = DEFAULT_NODE_ID_REF) { - foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) { + foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { if (node->getLinkedData() != NULL && node->getType() == NODE_TYPE_AGENT) { Avatar* avatar = (Avatar*)node->getLinkedData(); float distance; @@ -2029,7 +2029,7 @@ void Application::updateAvatars(float deltaTime, glm::vec3 mouseRayOrigin, glm:: bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::updateAvatars()"); - foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) { + foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { QMutexLocker(&node->getMutex()); if (node->getLinkedData()) { Avatar *avatar = (Avatar *)node->getLinkedData(); @@ -2657,7 +2657,7 @@ void Application::queryOctree(NODE_TYPE serverType, PACKET_TYPE packetType, Node int inViewServers = 0; int unknownJurisdictionServers = 0; - foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) { + foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { // only send to the NodeTypes that are serverType if (node->getActiveSocket() != NULL && node->getType() == serverType) { totalServers++; @@ -2717,7 +2717,7 @@ void Application::queryOctree(NODE_TYPE serverType, PACKET_TYPE packetType, Node NodeList* nodeList = NodeList::getInstance(); - foreach(SharedNodePointer node, nodeList->getNodeHash()) { + foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { // only send to the NodeTypes that are serverType if (node->getActiveSocket() != NULL && node->getType() == serverType) { @@ -3292,7 +3292,7 @@ void Application::displayOverlay() { int totalAvatars = 0, totalServers = 0; - foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) { + foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { node->getType() == NODE_TYPE_AGENT ? totalAvatars++ : totalServers++; } @@ -3406,7 +3406,7 @@ void Application::displayStats() { unsigned long totalPingVoxel = 0; int voxelServerCount = 0; - foreach(SharedNodePointer node, nodeList->getNodeHash()) { + foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { if (node->getType() == NODE_TYPE_VOXEL_SERVER) { totalPingVoxel += node->getPingMs(); voxelServerCount++; @@ -3757,7 +3757,7 @@ void Application::renderAvatars(bool forceRenderHead, bool selfAvatarOnly) { // Render avatars of other nodes NodeList* nodeList = NodeList::getInstance(); - foreach(SharedNodePointer node, nodeList->getNodeHash()) { + foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { QMutexLocker(&node->getMutex()); if (node->getLinkedData() != NULL && node->getType() == NODE_TYPE_AGENT) { diff --git a/interface/src/DataServerClient.cpp b/interface/src/DataServerClient.cpp index 34fe0b165c..306b68536a 100644 --- a/interface/src/DataServerClient.cpp +++ b/interface/src/DataServerClient.cpp @@ -145,7 +145,7 @@ void DataServerClient::processSendFromDataServer(unsigned char* packetData, int } else { // mesh URL for a UUID, find avatar in our list - foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) { + foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { if (node->getLinkedData() != NULL && node->getType() == NODE_TYPE_AGENT) { Avatar* avatar = (Avatar *) node->getLinkedData(); @@ -163,7 +163,7 @@ void DataServerClient::processSendFromDataServer(unsigned char* packetData, int Application::getInstance()->getProfile()->setSkeletonModelURL(QUrl(valueList[i])); } else { // skeleton URL for a UUID, find avatar in our list - foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) { + foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { if (node->getLinkedData() != NULL && node->getType() == NODE_TYPE_AGENT) { Avatar* avatar = (Avatar *) node->getLinkedData(); diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 7dfa4158cf..e66f4cb7f1 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -1605,7 +1605,7 @@ void VoxelSystem::falseColorizeBySource() { // create a bunch of colors we'll use during colorization - foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) { + foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { if (node->getType() == NODE_TYPE_VOXEL_SERVER) { uint16_t nodeID = VoxelTreeElement::getSourceNodeUUIDKey(node->getUUID()); int groupColor = voxelServerCount % NUMBER_OF_COLOR_GROUPS; diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 78be4a1864..2784e0a115 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -368,7 +368,7 @@ void Hand::updateCollisions() { glm::vec3 totalPenetration; // check other avatars - foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) { + foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { if (node->getLinkedData() && node->getType() == NODE_TYPE_AGENT) { Avatar* otherAvatar = (Avatar*)node->getLinkedData(); if (Menu::getInstance()->isOptionChecked(MenuOption::PlaySlaps)) { diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 1e6b2565ce..76f946d7a4 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -843,7 +843,7 @@ void MyAvatar::updateChatCircle(float deltaTime) { // find all circle-enabled members and sort by distance QVector sortedAvatars; - foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) { + foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { if (node->getLinkedData() && node->getType() == NODE_TYPE_AGENT) { SortedAvatar sortedAvatar; sortedAvatar.avatar = (Avatar*)node->getLinkedData(); diff --git a/interface/src/ui/VoxelStatsDialog.cpp b/interface/src/ui/VoxelStatsDialog.cpp index e154e30c74..9bf755b174 100644 --- a/interface/src/ui/VoxelStatsDialog.cpp +++ b/interface/src/ui/VoxelStatsDialog.cpp @@ -244,7 +244,7 @@ void VoxelStatsDialog::showOctreeServersOfType(int& serverCount, NODE_TYPE serve NodeList* nodeList = NodeList::getInstance(); - foreach(SharedNodePointer node, nodeList->getNodeHash()) { + foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { // only send to the NodeTypes that are NODE_TYPE_VOXEL_SERVER if (node->getType() == serverType) { serverCount++; diff --git a/libraries/octree/src/JurisdictionListener.cpp b/libraries/octree/src/JurisdictionListener.cpp index 60a3eddd57..ae27259f83 100644 --- a/libraries/octree/src/JurisdictionListener.cpp +++ b/libraries/octree/src/JurisdictionListener.cpp @@ -44,7 +44,7 @@ bool JurisdictionListener::queueJurisdictionRequest() { NodeList* nodeList = NodeList::getInstance(); - foreach(SharedNodePointer node, nodeList->getNodeHash()) { + foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { if (nodeList->getNodeActiveSocketOrPing(node.data()) && node->getType() == getNodeType()) { const HifiSockAddr* nodeAddress = node->getActiveSocket(); diff --git a/libraries/octree/src/OctreeEditPacketSender.cpp b/libraries/octree/src/OctreeEditPacketSender.cpp index b7a31f166b..4763ed055a 100644 --- a/libraries/octree/src/OctreeEditPacketSender.cpp +++ b/libraries/octree/src/OctreeEditPacketSender.cpp @@ -58,7 +58,7 @@ bool OctreeEditPacketSender::serversExist() const { bool atLeastOnJurisdictionMissing = false; // assume the best NodeList* nodeList = NodeList::getInstance(); - foreach(SharedNodePointer node, nodeList->getNodeHash()) { + foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { // only send to the NodeTypes that are getMyNodeType() if (node->getType() == getMyNodeType()) { if (nodeList->getNodeActiveSocketOrPing(node.data())) { @@ -87,7 +87,7 @@ bool OctreeEditPacketSender::serversExist() const { void OctreeEditPacketSender::queuePacketToNode(const QUuid& nodeUUID, unsigned char* buffer, ssize_t length) { NodeList* nodeList = NodeList::getInstance(); - foreach(SharedNodePointer node, nodeList->getNodeHash()) { + foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { // only send to the NodeTypes that are getMyNodeType() if (node->getType() == getMyNodeType() && ((node->getUUID() == nodeUUID) || (nodeUUID.isNull()))) { @@ -170,7 +170,7 @@ void OctreeEditPacketSender::queuePacketToNodes(unsigned char* buffer, ssize_t l // for a different server... So we need to actually manage multiple queued packets... one // for each server - foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) { + foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { // only send to the NodeTypes that are getMyNodeType() if (node->getActiveSocket() != NULL && node->getType() == getMyNodeType()) { QUuid nodeUUID = node->getUUID(); @@ -216,7 +216,7 @@ void OctreeEditPacketSender::queueOctreeEditMessage(PACKET_TYPE type, unsigned c // for a different server... So we need to actually manage multiple queued packets... one // for each server - foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) { + foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { // only send to the NodeTypes that are getMyNodeType() if (node->getActiveSocket() != NULL && node->getType() == getMyNodeType()) { QUuid nodeUUID = node->getUUID(); diff --git a/libraries/particles/src/ParticleCollisionSystem.cpp b/libraries/particles/src/ParticleCollisionSystem.cpp index 3ef831d9c7..0bf5db90f0 100644 --- a/libraries/particles/src/ParticleCollisionSystem.cpp +++ b/libraries/particles/src/ParticleCollisionSystem.cpp @@ -188,7 +188,7 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) { // loop through all the other avatars for potential interactions... - foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) { + foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { //qDebug() << "updateCollisionWithAvatars()... node:" << *node << "\n"; if (node->getLinkedData() && node->getType() == NODE_TYPE_AGENT) { // TODO: dot collidingPalm and hand velocities and skip collision when they are moving apart. diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index b95efb550b..972c617de3 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -110,7 +110,7 @@ void NodeList::setDomainHostname(const QString& domainHostname) { } void NodeList::timePingReply(const HifiSockAddr& nodeAddress, unsigned char *packetData) { - foreach(SharedNodePointer node, _nodeHash) { + foreach (const SharedNodePointer& node, _nodeHash) { if (node->getPublicSocket() == nodeAddress || node->getLocalSocket() == nodeAddress) { @@ -254,7 +254,7 @@ int NodeList::updateNodeWithData(Node *node, const HifiSockAddr& senderSockAddr, SharedNodePointer NodeList::nodeWithAddress(const HifiSockAddr &senderSockAddr) { // naively returns the first node that has a matching active HifiSockAddr // note that there can be multiple nodes that have a matching active socket, so this isn't a good way to uniquely identify - foreach(SharedNodePointer node, _nodeHash) { + foreach (const SharedNodePointer& node, _nodeHash) { if (node->getActiveSocket() && *node->getActiveSocket() == senderSockAddr) { return node; } @@ -721,7 +721,7 @@ SharedNodePointer NodeList::addOrUpdateNode(const QUuid& uuid, char nodeType, unsigned NodeList::broadcastToNodes(unsigned char* broadcastData, size_t dataBytes, const char* nodeTypes, int numNodeTypes) { unsigned n = 0; - foreach(SharedNodePointer node, _nodeHash) { + foreach (const SharedNodePointer& node, _nodeHash) { // only send to the NodeTypes we are asked to send to. if (memchr(nodeTypes, node->getType(), numNodeTypes)) { if (getNodeActiveSocketOrPing(node.data())) { @@ -737,7 +737,7 @@ unsigned NodeList::broadcastToNodes(unsigned char* broadcastData, size_t dataByt } void NodeList::pingInactiveNodes() { - foreach(SharedNodePointer node, _nodeHash) { + foreach (const SharedNodePointer& node, _nodeHash) { if (!node->getActiveSocket()) { // we don't have an active link to this node, ping it to set that up pingPublicAndLocalSocketsForInactiveNode(node.data()); @@ -756,7 +756,7 @@ const HifiSockAddr* NodeList::getNodeActiveSocketOrPing(Node* node) { void NodeList::activateSocketFromNodeCommunication(const HifiSockAddr& nodeAddress) { - foreach(SharedNodePointer node, _nodeHash) { + foreach (const SharedNodePointer& node, _nodeHash) { if (!node->getActiveSocket()) { // check both the public and local addresses for each node to see if we find a match // prioritize the private address so that we prune erroneous local matches @@ -774,7 +774,7 @@ void NodeList::activateSocketFromNodeCommunication(const HifiSockAddr& nodeAddre SharedNodePointer NodeList::soloNodeOfType(char nodeType) { if (memchr(SOLO_NODE_TYPES, nodeType, sizeof(SOLO_NODE_TYPES)) != NULL) { - foreach(SharedNodePointer node, _nodeHash) { + foreach (const SharedNodePointer& node, _nodeHash) { if (node->getType() == nodeType) { return node; } From 274989935d94c5f61352aa17a54b1fc62f5e5d19 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 14 Jan 2014 16:09:12 -0800 Subject: [PATCH 28/29] resolve conflicts on merge with upstream master --- interface/src/avatar/Avatar.cpp | 4 ++-- interface/src/avatar/MyAvatar.cpp | 2 +- libraries/avatars/src/AvatarData.cpp | 4 ++-- libraries/voxels/src/VoxelTreeElement.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) mode change 100755 => 100644 interface/src/avatar/Avatar.cpp diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp old mode 100755 new mode 100644 index fdace5becb..aae34cb358 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -146,8 +146,8 @@ glm::quat Avatar::getWorldAlignedOrientation () const { } void Avatar::simulate(float deltaTime, Transmitter* transmitter) { - if (_scale != _newScale) { - setScale(_newScale); + if (_scale != _targetScale) { + setScale(_targetScale); } // copy velocity so we can use it later for acceleration diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 9ba35a9f80..04f320f4c2 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -88,7 +88,7 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { } if (_scale != _newScale) { - float scale = (1.f - SMOOTHING_RATIO) * _scale + SMOOTHING_RATIO * _newScale; + float scale = (1.f - SMOOTHING_RATIO) * _scale + SMOOTHING_RATIO * _targetScale; setScale(scale); Application::getInstance()->getCamera()->setScale(scale); } diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index ff060f3e0f..4647ad5d35 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -29,7 +29,7 @@ AvatarData::AvatarData(Node* owningNode) : _bodyYaw(-90.0), _bodyPitch(0.0), _bodyRoll(0.0), - _newScale(1.0f), + _targetScale(1.0f), _handState(0), _keyState(NO_KEY_DOWN), _isChatCirclingEnabled(false), @@ -75,7 +75,7 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) { destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _bodyRoll); // Body scale - destinationBuffer += packFloatRatioToTwoByte(destinationBuffer, _newScale); + destinationBuffer += packFloatRatioToTwoByte(destinationBuffer, _targetScale); // Head rotation (NOTE: This needs to become a quaternion to save two bytes) destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headData->_yaw); diff --git a/libraries/voxels/src/VoxelTreeElement.h b/libraries/voxels/src/VoxelTreeElement.h index d30007aca1..1eee7e4a5b 100644 --- a/libraries/voxels/src/VoxelTreeElement.h +++ b/libraries/voxels/src/VoxelTreeElement.h @@ -92,4 +92,4 @@ protected: }; -#endif /* defined(__hifi__VoxelTreeElement__) */ +#endif /* defined(__hifi__VoxelTreeElement__) */ \ No newline at end of file From 4c2b67f6f3a9e18a8caed34a89809c73571a0d50 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 14 Jan 2014 16:16:06 -0800 Subject: [PATCH 29/29] Fix compile error. --- interface/src/avatar/MyAvatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 04f320f4c2..3f3de7241f 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -87,7 +87,7 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { _elapsedTimeMoving += deltaTime; } - if (_scale != _newScale) { + if (_scale != _targetScale) { float scale = (1.f - SMOOTHING_RATIO) * _scale + SMOOTHING_RATIO * _targetScale; setScale(scale); Application::getInstance()->getCamera()->setScale(scale);