From 5230b805d28328bddeaf781288e5ad40c8e1dac9 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 18 Feb 2015 19:24:29 +0100 Subject: [PATCH 01/56] Fix warnings --- interface/src/scripting/HMDScriptingInterface.cpp | 1 - interface/src/ui/ApplicationOverlay.cpp | 2 +- libraries/model/src/model/Light.cpp | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/interface/src/scripting/HMDScriptingInterface.cpp b/interface/src/scripting/HMDScriptingInterface.cpp index fe274b6878..f258fd695c 100644 --- a/interface/src/scripting/HMDScriptingInterface.cpp +++ b/interface/src/scripting/HMDScriptingInterface.cpp @@ -48,7 +48,6 @@ QScriptValue HMDScriptingInterface::getHUDLookAtPosition2D(QScriptContext* conte QScriptValue HMDScriptingInterface::getHUDLookAtPosition3D(QScriptContext* context, QScriptEngine* engine) { glm::vec3 result; - HMDScriptingInterface* hmdInterface = &HMDScriptingInterface::getInstance(); if ((&HMDScriptingInterface::getInstance())->getHUDLookAtPosition3D(result)) { return qScriptValueFromValue(engine, result); } diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 569ef0cf80..632e76c840 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -136,10 +136,10 @@ ApplicationOverlay::ApplicationOverlay() : _textureFov(glm::radians(DEFAULT_OCULUS_UI_ANGULAR_SIZE)), _textureAspectRatio(1.0f), _lastMouseMove(0), + _magnifier(true), _alpha(1.0f), _oculusUIRadius(1.0f), _crosshairTexture(0), - _magnifier(true), _previousBorderWidth(-1), _previousBorderHeight(-1), _previousMagnifierBottomLeft(), diff --git a/libraries/model/src/model/Light.cpp b/libraries/model/src/model/Light.cpp index 9616ed2106..a9425bed4b 100755 --- a/libraries/model/src/model/Light.cpp +++ b/libraries/model/src/model/Light.cpp @@ -76,7 +76,6 @@ void Light::setSpotAngle(float angle) { if (angle <= 0.f) { angle = 0.0f; } - float cosAngle = cos(angle); editSchema()._spot.x = cos(angle); editSchema()._spot.y = sin(angle); editSchema()._spot.z = angle; From a5b737314d931ab0a06535d799fd452939c2e270 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 18 Feb 2015 11:44:15 -0800 Subject: [PATCH 02/56] Add auto-scale to preferences dialog --- interface/src/ui/PreferencesDialog.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index e27875ce67..caab326f90 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -10,6 +10,7 @@ // #include +#include #include #include @@ -26,6 +27,18 @@ const int PREFERENCES_HEIGHT_PADDING = 20; +void scaleWidgetFontSizes(QWidget* widget, float scale) { + for (auto child : widget->findChildren()) { + if (child->parent() == widget) { + scaleWidgetFontSizes(child, scale); + } + } + QFont font = widget->font(); + qDebug() << "Pref: " << widget->objectName() << ": " << font.pointSizeF(); + font.setPointSizeF(font.pointSizeF() * scale); + widget->setFont(font); +} + PreferencesDialog::PreferencesDialog(QWidget* parent) : QDialog(parent) { @@ -46,8 +59,14 @@ PreferencesDialog::PreferencesDialog(QWidget* parent) : // move dialog to left side move(parentWidget()->geometry().topLeft()); setFixedHeight(parentWidget()->size().height() - PREFERENCES_HEIGHT_PADDING); + + auto glCanvas = DependencyManager::get(); + float dpiScale = 72.0f / glCanvas->logicalDpiX(); + + scaleWidgetFontSizes(ui.scrollArea, dpiScale); } + void PreferencesDialog::accept() { savePreferences(); close(); From ab542c3599e180a09abaac2b2773d679dde51c21 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 18 Feb 2015 12:21:06 -0800 Subject: [PATCH 03/56] Update DPI scaling to not update default fonts --- interface/src/ui/PreferencesDialog.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index caab326f90..56a6e33bc2 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -35,8 +35,10 @@ void scaleWidgetFontSizes(QWidget* widget, float scale) { } QFont font = widget->font(); qDebug() << "Pref: " << widget->objectName() << ": " << font.pointSizeF(); - font.setPointSizeF(font.pointSizeF() * scale); - widget->setFont(font); + if (font != QFont()) { + font.setPointSizeF(font.pointSizeF() * scale); + widget->setFont(font); + } } PreferencesDialog::PreferencesDialog(QWidget* parent) : @@ -61,9 +63,11 @@ PreferencesDialog::PreferencesDialog(QWidget* parent) : setFixedHeight(parentWidget()->size().height() - PREFERENCES_HEIGHT_PADDING); auto glCanvas = DependencyManager::get(); + + // All font sizes are based on 72 DPI. float dpiScale = 72.0f / glCanvas->logicalDpiX(); - scaleWidgetFontSizes(ui.scrollArea, dpiScale); + scaleWidgetFontSizes(this, dpiScale); } From 18a92464b5666f909b0575924215fdbad9552d3d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 18 Feb 2015 12:23:56 -0800 Subject: [PATCH 04/56] Remove custom font sizes on preferences dialog --- interface/ui/preferencesDialog.ui | 5 ----- 1 file changed, 5 deletions(-) diff --git a/interface/ui/preferencesDialog.ui b/interface/ui/preferencesDialog.ui index e9b0f43924..c413ed1266 100644 --- a/interface/ui/preferencesDialog.ui +++ b/interface/ui/preferencesDialog.ui @@ -133,7 +133,6 @@ Arial - 14 @@ -194,7 +193,6 @@ Arial - 14 @@ -276,7 +274,6 @@ Arial - 14 @@ -388,7 +385,6 @@ Arial - 13 @@ -508,7 +504,6 @@ Arial - 13 From c446e72226ba71519b46b815b1a6e884218a6907 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 18 Feb 2015 12:39:51 -0800 Subject: [PATCH 05/56] Add Face Tracking menu item to select the face tracker to use Includes new DDE Face Regression option. --- interface/src/Application.cpp | 10 ++++++++++ interface/src/Application.h | 2 ++ interface/src/Menu.cpp | 34 ++++++++++++++++++++++++-------- interface/src/Menu.h | 10 ++++++---- interface/src/devices/Visage.cpp | 3 ++- 5 files changed, 46 insertions(+), 13 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ce33b04777..4f771ccbf0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1601,6 +1601,16 @@ FaceTracker* Application::getActiveFaceTracker() { (visage->isActive() ? static_cast(visage.data()) : NULL))); } +void Application::setActiveFaceTracker() { +#ifdef HAVE_FACESHIFT + DependencyManager::get()->setTCPEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift)); +#endif + DependencyManager::get()->setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::DDEFaceRegression)); +#ifdef HAVE_VISAGE + DependencyManager::get()->updateEnabled(); +#endif +} + bool Application::exportEntities(const QString& filename, float x, float y, float z, float scale) { QVector entities; _entities.getTree()->findEntities(AACube(glm::vec3(x / (float)TREE_SCALE, diff --git a/interface/src/Application.h b/interface/src/Application.h index da29920ef9..2db120aa27 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -366,6 +366,8 @@ public slots: void notifyPacketVersionMismatch(); + void setActiveFaceTracker(); + private slots: void clearDomainOctreeDetails(); void timer(); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 46b6141ba9..1478a6d3d6 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -27,6 +27,7 @@ #include "audio/AudioIOStatsRenderer.h" #include "audio/AudioScope.h" #include "avatar/AvatarManager.h" +#include "devices/DDEFaceTracker.h" #include "devices/Faceshift.h" #include "devices/RealSense.h" #include "devices/SixenseManager.h" @@ -357,18 +358,35 @@ Menu::Menu() { dialogsManager.data(), SLOT(lodTools())); QMenu* avatarDebugMenu = developerMenu->addMenu("Avatar"); + + QMenu* faceTrackingMenu = avatarDebugMenu->addMenu("Face Tracking"); + { + QActionGroup* faceTrackerGroup = new QActionGroup(avatarDebugMenu); + + QAction* noFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::NoFaceTracking, + 0, true, + qApp, SLOT(setActiveFaceTracker())); + faceTrackerGroup->addAction(noFaceTracker); + #ifdef HAVE_FACESHIFT - addCheckableActionToQMenuAndActionHash(avatarDebugMenu, - MenuOption::Faceshift, - 0, - true, - DependencyManager::get().data(), - SLOT(setTCPEnabled(bool))); + QAction* faceshiftFaceTracker = addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::Faceshift, + 0, true, + qApp, SLOT(setActiveFaceTracker())); + faceTrackerGroup->addAction(faceshiftFaceTracker); #endif + + QAction* ddeFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::DDEFaceRegression, + 0, false, + qApp, SLOT(setActiveFaceTracker())); + faceTrackerGroup->addAction(ddeFaceTracker); + #ifdef HAVE_VISAGE - addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::Visage, 0, false, - DependencyManager::get().data(), SLOT(updateEnabled())); + QAction* visageFaceTracker = addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::Visage, + 0, false, + qApp, SLOT(setActiveFaceTracker())); + faceTrackerGroup->addAction(visageFaceTracker); #endif + } addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderSkeletonCollisionShapes); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderHeadCollisionShapes); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 19e51ad044..6dbc841a42 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -133,13 +133,12 @@ namespace MenuOption { const QString CollideWithEnvironment = "Collide With World Boundaries"; const QString Collisions = "Collisions"; const QString Console = "Console..."; + const QString ControlWithSpeech = "Control With Speech"; const QString CopyAddress = "Copy Address to Clipboard"; const QString CopyPath = "Copy Path to Clipboard"; - const QString ControlWithSpeech = "Control With Speech"; - const QString DeleteBookmark = "Delete Bookmark..."; - const QString DontRenderEntitiesAsScene = "Don't Render Entities as Scene"; - const QString DontDoPrecisionPicking = "Don't Do Precision Picking"; + const QString DDEFaceRegression = "DDE Face Regression"; const QString DecreaseAvatarSize = "Decrease Avatar Size"; + const QString DeleteBookmark = "Delete Bookmark..."; const QString DisableActivityLogger = "Disable Activity Logger"; const QString DisableAutoAdjustLOD = "Disable Automatically Adjusting LOD"; const QString DisableLightEntities = "Disable Light Entities"; @@ -152,7 +151,9 @@ namespace MenuOption { const QString DisplayModelElementChildProxies = "Display Model Element Children"; const QString DisplayModelElementProxy = "Display Model Element Bounds"; const QString DisplayTimingDetails = "Display Timing Details"; + const QString DontDoPrecisionPicking = "Don't Do Precision Picking"; const QString DontFadeOnOctreeServerChanges = "Don't Fade In/Out on Octree Server Changes"; + const QString DontRenderEntitiesAsScene = "Don't Render Entities as Scene"; const QString EchoLocalAudio = "Echo Local Audio"; const QString EchoServerAudio = "Echo Server Audio"; const QString EditEntitiesHelp = "Edit Entities Help..."; @@ -192,6 +193,7 @@ namespace MenuOption { const QString MuteEnvironment = "Mute Environment"; const QString NetworkSimulator = "Network Simulator..."; const QString NewVoxelCullingMode = "New Voxel Culling Mode"; + const QString NoFaceTracking = "None"; const QString ObeyEnvironmentalGravity = "Obey Environmental Gravity"; const QString OctreeStats = "Voxel and Entity Statistics"; const QString OffAxisProjection = "Off-Axis Projection"; diff --git a/interface/src/devices/Visage.cpp b/interface/src/devices/Visage.cpp index bdb33cc092..39bda83e61 100644 --- a/interface/src/devices/Visage.cpp +++ b/interface/src/devices/Visage.cpp @@ -174,7 +174,8 @@ void Visage::reset() { void Visage::updateEnabled() { setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Visage) && !(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift) && - DependencyManager::get()->isConnectedOrConnecting())); + DependencyManager::get()->isConnectedOrConnecting()) && + !Menu::getInstance()->isOptionChecked(MenuOption::DDEFaceRegression)); } void Visage::setEnabled(bool enabled) { From a66af77b23d843caf84799da3acc14da7c39161d Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 18 Feb 2015 12:40:59 -0800 Subject: [PATCH 06/56] Update DDE face tracker to work with menu item --- interface/src/Application.cpp | 1 + interface/src/devices/DdeFaceTracker.cpp | 84 ++++++++++-------------- interface/src/devices/DdeFaceTracker.h | 11 ++-- 3 files changed, 41 insertions(+), 55 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4f771ccbf0..ac73920399 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1728,6 +1728,7 @@ void Application::init() { // initialize our face trackers after loading the menu settings DependencyManager::get()->init(); + DependencyManager::get()->init(); DependencyManager::get()->init(); Leapmotion::init(); diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index d8766ca0ab..c4797c4018 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -44,58 +44,40 @@ struct Packet{ }; DdeFaceTracker::DdeFaceTracker() : -_lastReceiveTimestamp(0), -_reset(false), -_leftBlinkIndex(0), // see http://support.faceshift.com/support/articles/35129-export-of-blendshapes -_rightBlinkIndex(1), -_leftEyeOpenIndex(8), -_rightEyeOpenIndex(9), -_browDownLeftIndex(14), -_browDownRightIndex(15), -_browUpCenterIndex(16), -_browUpLeftIndex(17), -_browUpRightIndex(18), -_mouthSmileLeftIndex(28), -_mouthSmileRightIndex(29), -_jawOpenIndex(21) + DdeFaceTracker(QHostAddress::Any, DDE_FEATURE_POINT_SERVER_PORT) +{ + +} + +DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 port) : + _lastReceiveTimestamp(0), + _reset(false), + _leftBlinkIndex(0), // see http://support.faceshift.com/support/articles/35129-export-of-blendshapes + _rightBlinkIndex(1), + _leftEyeOpenIndex(8), + _rightEyeOpenIndex(9), + _browDownLeftIndex(14), + _browDownRightIndex(15), + _browUpCenterIndex(16), + _browUpLeftIndex(17), + _browUpRightIndex(18), + _mouthSmileLeftIndex(28), + _mouthSmileRightIndex(29), + _jawOpenIndex(21), + _host(host), + _port(port) { _blendshapeCoefficients.resize(NUM_EXPRESSION); connect(&_udpSocket, SIGNAL(readyRead()), SLOT(readPendingDatagrams())); connect(&_udpSocket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(socketErrorOccurred(QAbstractSocket::SocketError))); connect(&_udpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), SLOT(socketStateChanged(QAbstractSocket::SocketState))); - - bindTo(DDE_FEATURE_POINT_SERVER_PORT); -} - -DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 port) : -_lastReceiveTimestamp(0), -_reset(false), -_leftBlinkIndex(0), // see http://support.faceshift.com/support/articles/35129-export-of-blendshapes -_rightBlinkIndex(1), -_leftEyeOpenIndex(8), -_rightEyeOpenIndex(9), -_browDownLeftIndex(14), -_browDownRightIndex(15), -_browUpCenterIndex(16), -_browUpLeftIndex(17), -_browUpRightIndex(18), -_mouthSmileLeftIndex(28), -_mouthSmileRightIndex(29), -_jawOpenIndex(21) -{ - _blendshapeCoefficients.resize(NUM_EXPRESSION); - - connect(&_udpSocket, SIGNAL(readyRead()), SLOT(readPendingDatagrams())); - connect(&_udpSocket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(socketErrorOccurred(QAbstractSocket::SocketError))); - connect(&_udpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), SIGNAL(socketStateChanged(QAbstractSocket::SocketState))); - - bindTo(host, port); } DdeFaceTracker::~DdeFaceTracker() { - if(_udpSocket.isOpen()) + if (_udpSocket.isOpen()) { _udpSocket.close(); + } } void DdeFaceTracker::init() { @@ -110,15 +92,15 @@ void DdeFaceTracker::update() { } -void DdeFaceTracker::bindTo(quint16 port) { - bindTo(QHostAddress::Any, port); -} - -void DdeFaceTracker::bindTo(const QHostAddress& host, quint16 port) { - if(_udpSocket.isOpen()) { +void DdeFaceTracker::setEnabled(bool enabled) { + if (enabled) { + if (_udpSocket.isOpen()) { + _udpSocket.close(); + } + _udpSocket.bind(_host, _port); + } else { _udpSocket.close(); } - _udpSocket.bind(host, port); } bool DdeFaceTracker::isActive() const { @@ -135,7 +117,7 @@ void DdeFaceTracker::socketStateChanged(QAbstractSocket::SocketState socketState QString state; switch(socketState) { case QAbstractSocket::BoundState: - state = "Bounded"; + state = "Bound"; break; case QAbstractSocket::ClosingState: state = "Closing"; @@ -156,7 +138,7 @@ void DdeFaceTracker::socketStateChanged(QAbstractSocket::SocketState socketState state = "Unconnected"; break; } - qDebug() << "[Info] DDE Face Tracker Socket: " << socketState; + qDebug() << "[Info] DDE Face Tracker Socket: " << state; } void DdeFaceTracker::readPendingDatagrams() { diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h index 71a743cce0..bd5d066732 100644 --- a/interface/src/devices/DdeFaceTracker.h +++ b/interface/src/devices/DdeFaceTracker.h @@ -28,9 +28,6 @@ public: void reset(); void update(); - //sockets - void bindTo(quint16 port); - void bindTo(const QHostAddress& host, quint16 port); bool isActive() const; float getLeftBlink() const { return getBlendshapeCoefficient(_leftBlinkIndex); } @@ -47,7 +44,10 @@ public: float getMouthSize() const { return getBlendshapeCoefficient(_jawOpenIndex); } float getMouthSmileLeft() const { return getBlendshapeCoefficient(_mouthSmileLeftIndex); } float getMouthSmileRight() const { return getBlendshapeCoefficient(_mouthSmileRightIndex); } - + +public slots: + void setEnabled(bool enabled); + private slots: //sockets @@ -59,6 +59,9 @@ private: DdeFaceTracker(); DdeFaceTracker(const QHostAddress& host, quint16 port); ~DdeFaceTracker(); + + QHostAddress _host; + quint16 _port; float getBlendshapeCoefficient(int index) const; void decodePacket(const QByteArray& buffer); From d704af21acff0739d4b5537e127c5c31e3e897b9 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 18 Feb 2015 12:41:54 -0800 Subject: [PATCH 07/56] Generalize "faceshift" data handling to "facetracker" DDE face tracking data is now broadcast to other avatars. --- assignment-client/src/Agent.cpp | 2 +- interface/src/avatar/Head.cpp | 13 ++++--------- libraries/avatars/src/AvatarData.cpp | 14 +++++++------- libraries/avatars/src/AvatarData.h | 4 ++-- libraries/avatars/src/HeadData.cpp | 2 +- libraries/avatars/src/HeadData.h | 2 +- libraries/avatars/src/Player.cpp | 10 +++++----- 7 files changed, 21 insertions(+), 26 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 4755d9137a..323d5695ed 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -193,7 +193,7 @@ void Agent::run() { // setup an Avatar for the script to use ScriptableAvatar scriptedAvatar(&_scriptEngine); - scriptedAvatar.setForceFaceshiftConnected(true); + scriptedAvatar.setForceFaceTrackerConnected(true); // call model URL setters with empty URLs so our avatar, if user, will have the default models scriptedAvatar.setFaceModelURL(QUrl()); diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index afc1346ad8..52f1b3ee86 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -80,15 +80,10 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) { // Only use face trackers when not playing back a recording. if (!myAvatar->isPlaying()) { FaceTracker* faceTracker = Application::getInstance()->getActiveFaceTracker(); - auto dde = DependencyManager::get(); - auto faceshift = DependencyManager::get(); - - if ((_isFaceshiftConnected = (faceshift == faceTracker))) { + _isFaceTrackerConnected = faceTracker != NULL; + if (_isFaceTrackerConnected) { _blendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); - } else if (dde->isActive()) { - faceTracker = dde.data(); - _blendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); - } + } } // Twist the upper body to follow the rotation of the head, but only do this with my avatar, // since everyone else will see the full joint rotations for other people. @@ -109,7 +104,7 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) { _longTermAverageLoudness = glm::mix(_longTermAverageLoudness, _averageLoudness, glm::min(deltaTime / AUDIO_LONG_TERM_AVERAGING_SECS, 1.0f)); } - if (!(_isFaceshiftConnected || billboard)) { + if (!(_isFaceTrackerConnected || billboard)) { // Update eye saccades const float AVERAGE_MICROSACCADE_INTERVAL = 0.50f; const float AVERAGE_SACCADE_INTERVAL = 4.0f; diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 4c71c5e9ed..a3d330f84b 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -44,7 +44,7 @@ AvatarData::AvatarData() : _handState(0), _keyState(NO_KEY_DOWN), _isChatCirclingEnabled(false), - _forceFaceshiftConnected(false), + _forceFaceTrackerConnected(false), _hasNewJointRotations(true), _headData(NULL), _handData(NULL), @@ -136,8 +136,8 @@ QByteArray AvatarData::toByteArray() { if (!_headData) { _headData = new HeadData(this); } - if (_forceFaceshiftConnected) { - _headData->_isFaceshiftConnected = true; + if (_forceFaceTrackerConnected) { + _headData->_isFaceTrackerConnected = true; } QByteArray avatarDataByteArray; @@ -191,7 +191,7 @@ QByteArray AvatarData::toByteArray() { setAtBit(bitItems, HAND_STATE_FINGER_POINTING_BIT); } // faceshift state - if (_headData->_isFaceshiftConnected) { + if (_headData->_isFaceTrackerConnected) { setAtBit(bitItems, IS_FACESHIFT_CONNECTED); } if (_isChatCirclingEnabled) { @@ -208,7 +208,7 @@ QByteArray AvatarData::toByteArray() { } // If it is connected, pack up the data - if (_headData->_isFaceshiftConnected) { + if (_headData->_isFaceTrackerConnected) { memcpy(destinationBuffer, &_headData->_leftEyeBlink, sizeof(float)); destinationBuffer += sizeof(float); @@ -417,7 +417,7 @@ int AvatarData::parseDataAtOffset(const QByteArray& packet, int offset) { _handState = getSemiNibbleAt(bitItems, HAND_STATE_START_BIT) + (oneAtBit(bitItems, HAND_STATE_FINGER_POINTING_BIT) ? IS_FINGER_POINTING_FLAG : 0); - _headData->_isFaceshiftConnected = oneAtBit(bitItems, IS_FACESHIFT_CONNECTED); + _headData->_isFaceTrackerConnected = oneAtBit(bitItems, IS_FACESHIFT_CONNECTED); _isChatCirclingEnabled = oneAtBit(bitItems, IS_CHAT_CIRCLING_ENABLED); bool hasReferential = oneAtBit(bitItems, HAS_REFERENTIAL); @@ -436,7 +436,7 @@ int AvatarData::parseDataAtOffset(const QByteArray& packet, int offset) { } - if (_headData->_isFaceshiftConnected) { + if (_headData->_isFaceTrackerConnected) { float leftEyeBlink, rightEyeBlink, averageLoudness, browAudioLift; minPossibleSize += sizeof(leftEyeBlink) + sizeof(rightEyeBlink) + sizeof(averageLoudness) + sizeof(browAudioLift); minPossibleSize++; // one byte for blendDataSize diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 8848a261df..a8a330485c 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -241,7 +241,7 @@ public: Q_INVOKABLE void setBlendshape(QString name, float val) { _headData->setBlendshape(name, val); } - void setForceFaceshiftConnected(bool connected) { _forceFaceshiftConnected = connected; } + void setForceFaceTrackerConnected(bool connected) { _forceFaceTrackerConnected = connected; } // key state void setKeyState(KeyState s) { _keyState = s; } @@ -357,7 +357,7 @@ protected: KeyState _keyState; bool _isChatCirclingEnabled; - bool _forceFaceshiftConnected; + bool _forceFaceTrackerConnected; bool _hasNewJointRotations; // set in AvatarData, cleared in Avatar HeadData* _headData; diff --git a/libraries/avatars/src/HeadData.cpp b/libraries/avatars/src/HeadData.cpp index 8dec8368c9..7789385547 100644 --- a/libraries/avatars/src/HeadData.cpp +++ b/libraries/avatars/src/HeadData.cpp @@ -31,7 +31,7 @@ HeadData::HeadData(AvatarData* owningAvatar) : _torsoTwist(0.0f), _lookAtPosition(0.0f, 0.0f, 0.0f), _audioLoudness(0.0f), - _isFaceshiftConnected(false), + _isFaceTrackerConnected(false), _leftEyeBlink(0.0f), _rightEyeBlink(0.0f), _averageLoudness(0.0f), diff --git a/libraries/avatars/src/HeadData.h b/libraries/avatars/src/HeadData.h index cef5d5fbca..b180541914 100644 --- a/libraries/avatars/src/HeadData.h +++ b/libraries/avatars/src/HeadData.h @@ -92,7 +92,7 @@ protected: glm::vec3 _lookAtPosition; float _audioLoudness; - bool _isFaceshiftConnected; + bool _isFaceTrackerConnected; float _leftEyeBlink; float _rightEyeBlink; float _averageLoudness; diff --git a/libraries/avatars/src/Player.cpp b/libraries/avatars/src/Player.cpp index 2fabc39bac..2b92acb189 100644 --- a/libraries/avatars/src/Player.cpp +++ b/libraries/avatars/src/Player.cpp @@ -110,7 +110,7 @@ void Player::startPlaying() { } // Fake faceshift connection - _avatar->setForceFaceshiftConnected(true); + _avatar->setForceFaceTrackerConnected(true); qDebug() << "Recorder::startPlaying()"; setupAudioThread(); @@ -136,8 +136,8 @@ void Player::stopPlaying() { cleanupAudioThread(); _avatar->clearJointsData(); - // Turn off fake faceshift connection - _avatar->setForceFaceshiftConnected(false); + // Turn off fake face tracker connection + _avatar->setForceFaceTrackerConnected(false); if (_useAttachments) { _avatar->setAttachmentData(_currentContext.attachments); @@ -255,8 +255,8 @@ void Player::play() { HeadData* head = const_cast(_avatar->getHeadData()); if (head) { - // Make sure fake faceshift connection doesn't get turned off - _avatar->setForceFaceshiftConnected(true); + // Make sure fake face tracker connection doesn't get turned off + _avatar->setForceFaceTrackerConnected(true); QVector blendCoef(currentFrame.getBlendshapeCoefficients().size()); for (int i = 0; i < currentFrame.getBlendshapeCoefficients().size(); ++i) { From f44ec6da1295363b3643c94706fe358dd0606750 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 18 Feb 2015 12:49:11 -0800 Subject: [PATCH 08/56] Set global font size in preferencesDialog --- interface/ui/preferencesDialog.ui | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/interface/ui/preferencesDialog.ui b/interface/ui/preferencesDialog.ui index c413ed1266..6435f87f24 100644 --- a/interface/ui/preferencesDialog.ui +++ b/interface/ui/preferencesDialog.ui @@ -28,6 +28,11 @@ 16777215 + + + 13 + + From 0d60c09d03c60eabe16733ea02a723f94b7c7071 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 18 Feb 2015 13:33:19 -0800 Subject: [PATCH 09/56] Add UI font scaling to UIUtil --- interface/src/UIUtil.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ interface/src/UIUtil.h | 3 +++ 2 files changed, 43 insertions(+) diff --git a/interface/src/UIUtil.cpp b/interface/src/UIUtil.cpp index 3be6a824fa..5d01ddaa3d 100644 --- a/interface/src/UIUtil.cpp +++ b/interface/src/UIUtil.cpp @@ -12,6 +12,9 @@ #include #include +#include "DependencyManager.h" +#include "GLCanvas.h" + #include "UIUtil.h" int UIUtil::getWindowTitleBarHeight(const QWidget* window) { @@ -27,3 +30,40 @@ int UIUtil::getWindowTitleBarHeight(const QWidget* window) { return titleBarHeight; } + +// When setting the font size of a widget in points, the rendered text will be larger +// on Windows and Linux than on Mac OSX. This is because Windows and Linux use a DPI +// of 96, while OSX uses 72. +// In order to get consistent results across platforms, the font sizes need to be scaled +// based on the system DPI. +// This function will scale the font size of widget and all +// of its children recursively. +void UIUtil::scaleWidgetFontSizes(QWidget* widget) { + auto glCanvas = DependencyManager::get(); + + // This is the base dpi that we are targetting. This is based on Mac OSXs default DPI, + // and is the basis for all font sizes. + const float BASE_DPI = 72.0f; + +#ifdef Q_OS_MAC + const float NATIVE_DPI = 72.0f; +#else + const float NATIVE_DPI = 96.0f; +#endif + + float fontScale = (BASE_DPI / NATIVE_DPI) * (glCanvas->logicalDpiX() / NATIVE_DPI); + + internalScaleWidgetFontSizes(widget, fontScale); +} + +void UIUtil::internalScaleWidgetFontSizes(QWidget* widget, float scale) { + for (auto child : widget->findChildren()) { + if (child->parent() == widget) { + internalScaleWidgetFontSizes(child, scale); + } + } + + QFont font = widget->font(); + font.setPointSizeF(font.pointSizeF() * scale); + widget->setFont(font); +} diff --git a/interface/src/UIUtil.h b/interface/src/UIUtil.h index f9dc669840..0866101ebe 100644 --- a/interface/src/UIUtil.h +++ b/interface/src/UIUtil.h @@ -18,7 +18,10 @@ class UIUtil { public: static int getWindowTitleBarHeight(const QWidget* window); + static void scaleWidgetFontSizes(QWidget* widget); +private: + static void internalScaleWidgetFontSizes(QWidget* widget, float scale); }; #endif // hifi_UIUtil_h From ba66155d4653300fc701e62615bed73c2ea704d0 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 18 Feb 2015 13:33:39 -0800 Subject: [PATCH 10/56] Add font scaling to login dialog --- interface/src/ui/LoginDialog.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index 049e5bd1cd..3f0a69e578 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -21,6 +21,7 @@ #include "AccountManager.h" #include "ui_loginDialog.h" #include "LoginDialog.h" +#include "UIUtil.h" const QString FORGOT_PASSWORD_URL = "https://metaverse.highfidelity.io/users/password/new"; @@ -41,6 +42,8 @@ LoginDialog::LoginDialog(QWidget* parent) : this, &LoginDialog::handleLoginClicked); connect(_ui->closeButton, &QPushButton::clicked, this, &LoginDialog::close); + + UIUtil::scaleWidgetFontSizes(this); }; LoginDialog::~LoginDialog() { From 9550339a2a80a021c03cd63e8731a606a1a5168e Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 18 Feb 2015 13:34:01 -0800 Subject: [PATCH 11/56] Move preferences dialog font scaling to UIUtil --- interface/src/ui/PreferencesDialog.cpp | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 56a6e33bc2..29035dacd1 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -24,23 +24,10 @@ #include "PreferencesDialog.h" #include "Snapshot.h" #include "UserActivityLogger.h" +#include "UIUtil.h" const int PREFERENCES_HEIGHT_PADDING = 20; -void scaleWidgetFontSizes(QWidget* widget, float scale) { - for (auto child : widget->findChildren()) { - if (child->parent() == widget) { - scaleWidgetFontSizes(child, scale); - } - } - QFont font = widget->font(); - qDebug() << "Pref: " << widget->objectName() << ": " << font.pointSizeF(); - if (font != QFont()) { - font.setPointSizeF(font.pointSizeF() * scale); - widget->setFont(font); - } -} - PreferencesDialog::PreferencesDialog(QWidget* parent) : QDialog(parent) { @@ -67,7 +54,7 @@ PreferencesDialog::PreferencesDialog(QWidget* parent) : // All font sizes are based on 72 DPI. float dpiScale = 72.0f / glCanvas->logicalDpiX(); - scaleWidgetFontSizes(this, dpiScale); + UIUtil::scaleWidgetFontSizes(this); } From e048f7a36c53bb1e431832862e57c8610fd12d5e Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 18 Feb 2015 13:34:28 -0800 Subject: [PATCH 12/56] Add font scaling to running scripts window --- interface/src/ui/RunningScriptsWidget.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/ui/RunningScriptsWidget.cpp b/interface/src/ui/RunningScriptsWidget.cpp index 4346d813bb..86944e8cfd 100644 --- a/interface/src/ui/RunningScriptsWidget.cpp +++ b/interface/src/ui/RunningScriptsWidget.cpp @@ -64,6 +64,8 @@ RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) : connect(ui->loadScriptFromURLButton, &QPushButton::clicked, Application::getInstance(), &Application::loadScriptURLDialog); connect(&_signalMapper, SIGNAL(mapped(QString)), Application::getInstance(), SLOT(stopScript(const QString&))); + + UIUtil::scaleWidgetFontSizes(this); } RunningScriptsWidget::~RunningScriptsWidget() { From a069a2f21c95500b5154f7b83440cdba09183412 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 18 Feb 2015 13:34:48 -0800 Subject: [PATCH 13/56] Add default font to running scripts window --- interface/ui/runningScriptsWidget.ui | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/interface/ui/runningScriptsWidget.ui b/interface/ui/runningScriptsWidget.ui index ec078681e3..34b288ad7a 100644 --- a/interface/ui/runningScriptsWidget.ui +++ b/interface/ui/runningScriptsWidget.ui @@ -10,6 +10,12 @@ 728 + + + Helvetica,Arial,sans-serif + 13 + + Running Scripts From 889851f6ea914ec146aaa7dc91d5777084c5cb36 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 18 Feb 2015 13:51:50 -0800 Subject: [PATCH 14/56] Fix typo --- 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 ac73920399..01a2d9608b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1603,7 +1603,7 @@ FaceTracker* Application::getActiveFaceTracker() { void Application::setActiveFaceTracker() { #ifdef HAVE_FACESHIFT - DependencyManager::get()->setTCPEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift)); + DependencyManager::get()->setTCPEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift)); #endif DependencyManager::get()->setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::DDEFaceRegression)); #ifdef HAVE_VISAGE From 4a383ff17723d472b61d6ead1ef96f622b2fd453 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 18 Feb 2015 13:56:41 -0800 Subject: [PATCH 15/56] Update font sizes in running scripts panel --- interface/ui/runningScriptsWidget.ui | 37 ++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/interface/ui/runningScriptsWidget.ui b/interface/ui/runningScriptsWidget.ui index 34b288ad7a..0e6aebf9ac 100644 --- a/interface/ui/runningScriptsWidget.ui +++ b/interface/ui/runningScriptsWidget.ui @@ -37,6 +37,12 @@ 141 + + + Helvetica,Arial,sans-serif + 13 + + 0 @@ -197,8 +203,14 @@ font: bold 16pt; 0 + + + Helvetica,Arial,sans-serif + 14 + + - font: 14pt; color: #5f5f5f; margin: 2px; + color: #5f5f5f; margin: 2px; There are no scripts running. @@ -261,12 +273,15 @@ font: bold 16pt; 0 + + + Helvetica,Arial,sans-serif + 14 + + Qt::LeftToRight - - font-size: 14pt; - 0 @@ -285,6 +300,12 @@ font: bold 16pt; + + + Helvetica,Arial,sans-serif + 14 + + 0 @@ -306,8 +327,14 @@ font: bold 16pt; + + + Helvetica,Arial,sans-serif + 14 + + - font: 14pt; color: #5f5f5f; margin: 2px; + color: #5f5f5f; margin: 2px; Tip From ff1fb07b2d2241ed760e27ef9eb9f62deea6ce32 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 18 Feb 2015 14:04:02 -0800 Subject: [PATCH 16/56] Add high-dpi support to scaleWidgetFontSizes --- interface/src/UIUtil.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/interface/src/UIUtil.cpp b/interface/src/UIUtil.cpp index 5d01ddaa3d..27f40539a4 100644 --- a/interface/src/UIUtil.cpp +++ b/interface/src/UIUtil.cpp @@ -51,7 +51,14 @@ void UIUtil::scaleWidgetFontSizes(QWidget* widget) { const float NATIVE_DPI = 96.0f; #endif - float fontScale = (BASE_DPI / NATIVE_DPI) * (glCanvas->logicalDpiX() / NATIVE_DPI); + // Scale fonts based on the native dpi. On Windows, where the native DPI is 96, + // the scale will be: 72.0 / 96.0 = 0.75 + float fontScale = (BASE_DPI / NATIVE_DPI); + + // Scale the font further by the system's DPI settings. If using a 2x high-dpi screen + // on Windows, for example, the font will be further scaled by: 192.0 / 96.0 = 2.0 + // This would give a final scale of: 0.75 * 2.0 = 1.5 + fontScale *= (glCanvas->logicalDpiX() / NATIVE_DPI); internalScaleWidgetFontSizes(widget, fontScale); } From 7dab39a2f19d3ed3336baf4fcb873764f67f65a5 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 18 Feb 2015 14:16:33 -0800 Subject: [PATCH 17/56] Add qDebug message to scaleWidgetFontSizes --- interface/src/UIUtil.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/UIUtil.cpp b/interface/src/UIUtil.cpp index 27f40539a4..d39b3229aa 100644 --- a/interface/src/UIUtil.cpp +++ b/interface/src/UIUtil.cpp @@ -60,6 +60,8 @@ void UIUtil::scaleWidgetFontSizes(QWidget* widget) { // This would give a final scale of: 0.75 * 2.0 = 1.5 fontScale *= (glCanvas->logicalDpiX() / NATIVE_DPI); + qDebug() << "Scaling widgets by: " << fontScale; + internalScaleWidgetFontSizes(widget, fontScale); } From b2e1d8a38c6941e82641c65e1298cd53cf8664f4 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 18 Feb 2015 14:37:56 -0800 Subject: [PATCH 18/56] Remove font scaling based on system DPI --- interface/src/UIUtil.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/UIUtil.cpp b/interface/src/UIUtil.cpp index d39b3229aa..9de2ad35e9 100644 --- a/interface/src/UIUtil.cpp +++ b/interface/src/UIUtil.cpp @@ -58,7 +58,7 @@ void UIUtil::scaleWidgetFontSizes(QWidget* widget) { // Scale the font further by the system's DPI settings. If using a 2x high-dpi screen // on Windows, for example, the font will be further scaled by: 192.0 / 96.0 = 2.0 // This would give a final scale of: 0.75 * 2.0 = 1.5 - fontScale *= (glCanvas->logicalDpiX() / NATIVE_DPI); + // fontScale *= (glCanvas->logicalDpiX() / NATIVE_DPI); qDebug() << "Scaling widgets by: " << fontScale; From 51f5719e0ff90577f6d6e07a38e7bb9da2ce0674 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 18 Feb 2015 14:59:52 -0800 Subject: [PATCH 19/56] Update font sizes in running scripts window --- interface/ui/runningScriptsWidget.ui | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/interface/ui/runningScriptsWidget.ui b/interface/ui/runningScriptsWidget.ui index 0e6aebf9ac..852d61a7ba 100644 --- a/interface/ui/runningScriptsWidget.ui +++ b/interface/ui/runningScriptsWidget.ui @@ -125,6 +125,12 @@ font: bold 16pt; 0 + + + Helvetica,Arial,sans-serif + 13 + + reloadStopButtonArea { padding: 0 } @@ -143,6 +149,12 @@ font: bold 16pt; + + + Helvetica,Arial,sans-serif + 13 + + Reload all @@ -150,6 +162,12 @@ font: bold 16pt; + + + Helvetica,Arial,sans-serif + 13 + + Stop all @@ -179,6 +197,12 @@ font: bold 16pt; 0 + + + Helvetica,Arial,sans-serif + 13 + + 0 From 24d03deb210201521ae7215198c4d3a0b4827451 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 18 Feb 2015 15:02:44 -0800 Subject: [PATCH 20/56] Fix typo --- interface/src/Menu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 1478a6d3d6..bd609a6840 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -27,7 +27,7 @@ #include "audio/AudioIOStatsRenderer.h" #include "audio/AudioScope.h" #include "avatar/AvatarManager.h" -#include "devices/DDEFaceTracker.h" +#include "devices/DdeFaceTracker.h" #include "devices/Faceshift.h" #include "devices/RealSense.h" #include "devices/SixenseManager.h" From 2828b65bea550500bdcde6b8523278cd6ab4d278 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 18 Feb 2015 15:09:41 -0800 Subject: [PATCH 21/56] Add scaling for high-dpi Windows/Linux displays --- .../src/scripting/ControllerScriptingInterface.cpp | 14 +++++++++++++- interface/src/ui/ApplicationOverlay.cpp | 12 +++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index 929a763e70..a871adeb08 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -271,7 +271,19 @@ void ControllerScriptingInterface::releaseJoystick(int joystickIndex) { glm::vec2 ControllerScriptingInterface::getViewportDimensions() const { auto glCanvas = DependencyManager::get(); - return glm::vec2(glCanvas->width(), glCanvas->height()); +#ifdef Q_OS_MAC + const float dpiScaleX = 1.0f; + const float dpiScaleY = 1.0f; +#else + const float NATIVE_DPI = 96.0f; + const float dpiScaleX = NATIVE_DPI / glCanvas->logicalDpiX(); + const float dpiScaleY = NATIVE_DPI / glCanvas->logicalDpiY(); +#endif + + const float width = glCanvas->width() / dpiScaleX; + const float height = glCanvas->height() / dpiScaleY; + + return glm::vec2(width, height); } AbstractInputController* ControllerScriptingInterface::createInputController(const QString& deviceName, const QString& tracker) { diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index f9437221e5..16d6dbca02 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -203,7 +203,17 @@ void ApplicationOverlay::renderOverlay(bool renderToTexture) { const float NEAR_CLIP = -10000; const float FAR_CLIP = 10000; glLoadIdentity(); - glOrtho(0, glCanvas->width(), glCanvas->height(), 0, NEAR_CLIP, FAR_CLIP); + +#ifdef Q_OS_MAC + // OSX will take care of scaling for us + const float dpiScaleX = 1.0f; + const float dpiScaleY = 1.0f; +#else + const float NATIVE_DPI = 96.0f; + const float dpiScaleX = NATIVE_DPI / glCanvas->logicalDpiX(); + const float dpiScaleY = NATIVE_DPI / glCanvas->logicalDpiY(); +#endif + glOrtho(0, glCanvas->width() * dpiScaleX, glCanvas->height() * dpiScaleY, 0, NEAR_CLIP, FAR_CLIP); glMatrixMode(GL_MODELVIEW); From 9b719273ab1aa2e8fe3e9111d390d512aad6cc51 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 18 Feb 2015 15:30:39 -0800 Subject: [PATCH 22/56] Fix dpi scaling in getViewportDimensions --- interface/src/scripting/ControllerScriptingInterface.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index a871adeb08..1c9cccf26f 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -280,8 +280,8 @@ glm::vec2 ControllerScriptingInterface::getViewportDimensions() const { const float dpiScaleY = NATIVE_DPI / glCanvas->logicalDpiY(); #endif - const float width = glCanvas->width() / dpiScaleX; - const float height = glCanvas->height() / dpiScaleY; + const float width = glCanvas->width() * dpiScaleX; + const float height = glCanvas->height() * dpiScaleY; return glm::vec2(width, height); } From 22d46e3e6ba239407f5d8c49fe18b6815e679be9 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 18 Feb 2015 15:33:24 -0800 Subject: [PATCH 23/56] Update runningscripts script font to match parent --- interface/src/ui/RunningScriptsWidget.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/ui/RunningScriptsWidget.cpp b/interface/src/ui/RunningScriptsWidget.cpp index 86944e8cfd..9ff600675f 100644 --- a/interface/src/ui/RunningScriptsWidget.cpp +++ b/interface/src/ui/RunningScriptsWidget.cpp @@ -105,6 +105,7 @@ void RunningScriptsWidget::setRunningScripts(const QStringList& list) { hash.insert(list.at(i), 1); } QWidget* row = new QWidget(ui->scriptListWidget); + row->setFont(ui->scriptListWidget->font()); row->setLayout(new QHBoxLayout(row)); QUrl url = QUrl(list.at(i)); From 03eb1a984f5501a655b1fd81840a22dfd4c5d8a3 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 18 Feb 2015 16:15:53 -0800 Subject: [PATCH 24/56] Revert "Fix dpi scaling in getViewportDimensions" This reverts commit 9b719273ab1aa2e8fe3e9111d390d512aad6cc51. --- interface/src/scripting/ControllerScriptingInterface.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index 1c9cccf26f..a871adeb08 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -280,8 +280,8 @@ glm::vec2 ControllerScriptingInterface::getViewportDimensions() const { const float dpiScaleY = NATIVE_DPI / glCanvas->logicalDpiY(); #endif - const float width = glCanvas->width() * dpiScaleX; - const float height = glCanvas->height() * dpiScaleY; + const float width = glCanvas->width() / dpiScaleX; + const float height = glCanvas->height() / dpiScaleY; return glm::vec2(width, height); } From 4751974c459ac25f5e29ec4b60037bdcd32b82cb Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 18 Feb 2015 16:16:50 -0800 Subject: [PATCH 25/56] Revert "Add scaling for high-dpi Windows/Linux displays" This reverts commit 2828b65bea550500bdcde6b8523278cd6ab4d278. --- .../src/scripting/ControllerScriptingInterface.cpp | 14 +------------- interface/src/ui/ApplicationOverlay.cpp | 12 +----------- 2 files changed, 2 insertions(+), 24 deletions(-) diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index a871adeb08..929a763e70 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -271,19 +271,7 @@ void ControllerScriptingInterface::releaseJoystick(int joystickIndex) { glm::vec2 ControllerScriptingInterface::getViewportDimensions() const { auto glCanvas = DependencyManager::get(); -#ifdef Q_OS_MAC - const float dpiScaleX = 1.0f; - const float dpiScaleY = 1.0f; -#else - const float NATIVE_DPI = 96.0f; - const float dpiScaleX = NATIVE_DPI / glCanvas->logicalDpiX(); - const float dpiScaleY = NATIVE_DPI / glCanvas->logicalDpiY(); -#endif - - const float width = glCanvas->width() / dpiScaleX; - const float height = glCanvas->height() / dpiScaleY; - - return glm::vec2(width, height); + return glm::vec2(glCanvas->width(), glCanvas->height()); } AbstractInputController* ControllerScriptingInterface::createInputController(const QString& deviceName, const QString& tracker) { diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 16d6dbca02..f9437221e5 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -203,17 +203,7 @@ void ApplicationOverlay::renderOverlay(bool renderToTexture) { const float NEAR_CLIP = -10000; const float FAR_CLIP = 10000; glLoadIdentity(); - -#ifdef Q_OS_MAC - // OSX will take care of scaling for us - const float dpiScaleX = 1.0f; - const float dpiScaleY = 1.0f; -#else - const float NATIVE_DPI = 96.0f; - const float dpiScaleX = NATIVE_DPI / glCanvas->logicalDpiX(); - const float dpiScaleY = NATIVE_DPI / glCanvas->logicalDpiY(); -#endif - glOrtho(0, glCanvas->width() * dpiScaleX, glCanvas->height() * dpiScaleY, 0, NEAR_CLIP, FAR_CLIP); + glOrtho(0, glCanvas->width(), glCanvas->height(), 0, NEAR_CLIP, FAR_CLIP); glMatrixMode(GL_MODELVIEW); From a8999964f6dbb266e8bbf5bc9eba8aed13d6b024 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 18 Feb 2015 16:21:51 -0800 Subject: [PATCH 26/56] Cleanup dpi scaling comments --- interface/src/UIUtil.cpp | 14 +++----------- interface/src/ui/PreferencesDialog.cpp | 6 ------ 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/interface/src/UIUtil.cpp b/interface/src/UIUtil.cpp index 9de2ad35e9..c907c2b8e9 100644 --- a/interface/src/UIUtil.cpp +++ b/interface/src/UIUtil.cpp @@ -33,9 +33,8 @@ int UIUtil::getWindowTitleBarHeight(const QWidget* window) { // When setting the font size of a widget in points, the rendered text will be larger // on Windows and Linux than on Mac OSX. This is because Windows and Linux use a DPI -// of 96, while OSX uses 72. -// In order to get consistent results across platforms, the font sizes need to be scaled -// based on the system DPI. +// of 96, while OSX uses 72. In order to get consistent results across platforms, the +// font sizes need to be scaled based on the system DPI. // This function will scale the font size of widget and all // of its children recursively. void UIUtil::scaleWidgetFontSizes(QWidget* widget) { @@ -53,14 +52,7 @@ void UIUtil::scaleWidgetFontSizes(QWidget* widget) { // Scale fonts based on the native dpi. On Windows, where the native DPI is 96, // the scale will be: 72.0 / 96.0 = 0.75 - float fontScale = (BASE_DPI / NATIVE_DPI); - - // Scale the font further by the system's DPI settings. If using a 2x high-dpi screen - // on Windows, for example, the font will be further scaled by: 192.0 / 96.0 = 2.0 - // This would give a final scale of: 0.75 * 2.0 = 1.5 - // fontScale *= (glCanvas->logicalDpiX() / NATIVE_DPI); - - qDebug() << "Scaling widgets by: " << fontScale; + float fontScale = BASE_DPI / NATIVE_DPI; internalScaleWidgetFontSizes(widget, fontScale); } diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 29035dacd1..1a3ad541c9 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -49,15 +49,9 @@ PreferencesDialog::PreferencesDialog(QWidget* parent) : move(parentWidget()->geometry().topLeft()); setFixedHeight(parentWidget()->size().height() - PREFERENCES_HEIGHT_PADDING); - auto glCanvas = DependencyManager::get(); - - // All font sizes are based on 72 DPI. - float dpiScale = 72.0f / glCanvas->logicalDpiX(); - UIUtil::scaleWidgetFontSizes(this); } - void PreferencesDialog::accept() { savePreferences(); close(); From 4a8e3193a9c44292df6458fc63106b4605179f6e Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 19 Feb 2015 12:01:27 -0800 Subject: [PATCH 27/56] Add more comments to UIUtil::scaleWidgetFontSizes --- interface/src/UIUtil.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/interface/src/UIUtil.cpp b/interface/src/UIUtil.cpp index c907c2b8e9..19d3a51917 100644 --- a/interface/src/UIUtil.cpp +++ b/interface/src/UIUtil.cpp @@ -37,6 +37,12 @@ int UIUtil::getWindowTitleBarHeight(const QWidget* window) { // font sizes need to be scaled based on the system DPI. // This function will scale the font size of widget and all // of its children recursively. +// +// When creating widgets, if a font size isn't explicitly set Qt will choose a +// reasonable, but often different font size across platforms. This means +// YOU SHOUD EXPLICITLY SET ALL FONT SIZES and call this function OR not use +// this function at all. If you mix both you will end up with inconsistent results +// across platforms. void UIUtil::scaleWidgetFontSizes(QWidget* widget) { auto glCanvas = DependencyManager::get(); @@ -57,6 +63,8 @@ void UIUtil::scaleWidgetFontSizes(QWidget* widget) { internalScaleWidgetFontSizes(widget, fontScale); } +// Depth-first traversal through widget hierarchy. It is important to do a depth-first +// traversal because modifying the font size of a parent node can affect children. void UIUtil::internalScaleWidgetFontSizes(QWidget* widget, float scale) { for (auto child : widget->findChildren()) { if (child->parent() == widget) { From 4dfe7257214925bc4a7a91f2e52ad8d31ca8fe6d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 19 Feb 2015 14:02:15 -0800 Subject: [PATCH 28/56] Update preferences dialog to use layouts throughout --- interface/ui/preferencesDialog.ui | 4608 +++++++++++++++-------------- 1 file changed, 2316 insertions(+), 2292 deletions(-) diff --git a/interface/ui/preferencesDialog.ui b/interface/ui/preferencesDialog.ui index 6435f87f24..13894a2592 100644 --- a/interface/ui/preferencesDialog.ui +++ b/interface/ui/preferencesDialog.ui @@ -33,1075 +33,567 @@ 13 - - - - 0 - 0 - 500 - 491 - - - - - 0 - 0 - - - - QFrame::NoFrame - - - QFrame::Plain - - + + 0 - - true + + 0 - - - - 0 - -825 - 485 - 1611 - - - - + + 0 + + + 0 + + + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Plain + + 0 - - 30 + + true - - 0 - - - 30 - - - 30 - - - - - - 0 - 40 - - - - - 0 - 40 - - - - - Arial - 18 - 75 - true - - - - color:#29967e - - - Avatar basics - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - 0 - - - - - - - - 0 - 0 - - - - - 0 - 28 - - - - - Arial - - - - <html><head/><body><p>Avatar display name <span style=" color:#909090;">(optional)</span></p></body></html> - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - displayNameEdit - - - - - - - - 0 - 0 - - - - - 280 - 0 - - - - - Arial - - - - Qt::LeftToRight - - - - - - Not showing a name - - - - - - - - 0 - 0 - - - - - 0 - 28 - - - - - Arial - - - - Head - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - 0 - - - snapshotLocationEdit - - - - - - - - - - 0 - 0 - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 5 - 20 - - - - - - - - - Arial - - - - Browse - - - - 0 - 0 - - - - - - - - - - - 0 - 0 - - - - - 0 - 28 - - - - - Arial - - - - Body - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - skeletonURLEdit - - - - - - - - - - 0 - 0 - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 5 - 20 - - - - - - - - - Arial - - - - Browse - - - - 0 - 0 - - - - - - - - - - - 0 - 0 - - - - - 0 - 40 - - - - - Arial - 18 - 75 - true - - - - color:#29967e - - - Snapshots - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - - - 0 - 0 - - - - - 0 - 22 - - - - - Arial - - - - Place my Snapshots here: - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - 0 - - - snapshotLocationEdit - - - - - - - - - - 0 - 0 - - - - - Arial - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 5 - 20 - - - - - - - - - Arial - - - - Browse - - - - 0 - 0 - - - - - - - - - - - 0 - 0 - - - - - 0 - 40 - - - - - Arial - 18 - 75 - true - - - - color:#29967e - - - Scripts - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - - - 0 - 0 - - - - - 0 - 22 - - - - - Arial - - - - Load scripts from this directory: - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - 0 - - - snapshotLocationEdit - - - - - - - - - - 0 - 0 - - - - - Arial - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 5 - 20 - - - - - - - - - Arial - - - - Browse - - - - 0 - 0 - - - - - - - - - - - 0 - 0 - - - - - 150 - 0 - - - - - 300 - 0 - - - - - Arial - - - - Load Default Scripts - - - - - - - - 0 - 0 - - - - - 0 - 40 - - - - - Arial - 18 - 75 - true - - - - color:#29967e - - - Privacy - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - 0 - - - snapshotLocationEdit - - - - - - - - 0 - 0 - - - - - 32 - 28 - - - - - 0 - 0 - - - - - Arial - - - - Send data - - - - 0 - 0 - - - - - - - - - 0 - 0 - - - - - 0 - 40 - - - - - Arial - 18 - 75 - true - - - - color:#29967e - - - Avatar tuning - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - + + + + 0 + -107 + 485 + 1550 + + + 0 - - 7 + + 30 - + 0 + + 30 + - 7 + 30 - + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + Arial + 18 + 75 + true - + color:#29967e; - Real world vertical field of view (angular size of monitor) + Avatar basics - + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 0 - - fieldOfViewSpin + + 7 - + + 7 + + + + + + Arial + + + + <html><head/><body><p>Avatar display name <span style=" color:#909090;">(optional)</span></p></body></html> + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + displayNameEdit + + + + + + + 4 + + + 140 + + + 4 + + + + + + Arial + + + + Qt::LeftToRight + + + Not showing a name + + + + + + - - - - Arial - - - - Qt::Horizontal - - - - 0 - 0 - - - - - - - - - 100 - 0 - - - - - 95 - 36 - - - - - Arial - - - - 1 - - - 180 - - - - - - - - - 0 - - - 7 - - - 0 - - - 7 - - - - - - Arial - - - - - - - Vertical field of view - - + + 0 - - fieldOfViewSpin + + 7 - + + 7 + + + + + + Arial + + + + Head + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + snapshotLocationEdit + + + + + + + 0 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 5 + 20 + + + + + + + + + Arial + + + + Browse + + + + 0 + 0 + + + + + + + - - - - Arial - - - - Qt::Horizontal - - - - 0 - 0 - - - - - - - - - 0 - 0 - - - - - 100 - 0 - - - - - 95 - 36 - - - - - Arial - - - - 1 - - - 180 - - - - - - - - - 0 - - - 8 - - - 8 - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 25 - - - - - Arial - - - - Lean scale (applies to Faceshift users) - - + + 0 - - leanScaleSpin + + 7 - + + 7 + + + + + + Arial + + + + Body + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + skeletonURLEdit + + + + + + + 0 + + + + + + 0 + 0 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 5 + 20 + + + + + + + + + Arial + + + + Browse + + + + 0 + 0 + + + + + + + - - - - Arial - - + - Qt::Horizontal + Qt::Vertical - QSizePolicy::Expanding + QSizePolicy::Fixed - 40 - 10 - - - - - - - - - 0 - 0 - - - - - 100 - 0 - - - - - Arial - - - - - - - - - - 0 - - - 7 - - - 0 - - - 7 - - - - - - Arial - - - - Avatar scale <span style=" color:#909090;">(default is 1.0)</span> - - - 0 - - - avatarScaleSpin - - - - - - - - Arial - - - - Qt::Horizontal - - - - 40 + 20 20 - - - - 100 - 0 - - - - - 70 - 16777215 - - + Arial + 18 + 75 + true - - - - - - - - 0 - - - 7 - - - 0 - - - 7 - - - - - - Arial - + + color:#29967e - Pupil dillation + Snapshots - - 0 - - - pupilDilationSlider + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - Arial - + + + 0 + + 7 + + + 0 + + + + + + Arial + + + + Place my Snapshots here: + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + 0 + + + snapshotLocationEdit + + + + + + + 0 + + + + + + Arial + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 5 + 20 + + + + + + + + + Arial + + + + Browse + + + + 0 + 0 + + + + + + + + + + - Qt::Horizontal + Qt::Vertical + + + QSizePolicy::Fixed - 40 + 20 20 - + + + + Arial + 18 + 75 + true + + + + color:#29967e + + + Scripts + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + + 0 + + + 7 + + + 0 + + + + + + Arial + + + + Load scripts from this directory: + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + 0 + + + snapshotLocationEdit + + + + + + + 0 + + + + + + 0 + 0 + + + + + Arial + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 5 + 20 + + + + + + + + + Arial + + + + Browse + + + + 0 + 0 + + + + + + + + + + 0 @@ -1110,1456 +602,1988 @@ - 130 + 150 + 0 + + + + + 300 0 - - - Arial - - - - Qt::Horizontal - - - - - - - - - 0 - - - 7 - - - 0 - - - 7 - - - Arial - Faceshift eye detection - - - 0 - - - faceshiftEyeDeflectionSider + Load Default Scripts - - - - Arial - - + - Qt::Horizontal + Qt::Vertical + + + QSizePolicy::Fixed - 40 + 20 20 - + + + + Arial + 18 + 75 + true + + + + color:#29967e + + + Privacy + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + 0 + + + snapshotLocationEdit + + + + + - + 0 0 - 130 - 0 + 32 + 28 - - - Arial - - - - Qt::Horizontal - - - - - - - - - 0 - - - 7 - - - 0 - - - 7 - - - - - - Arial - - - - Faceshift hostname - - - 0 - - - faceshiftHostnameEdit - - - - - - - - Arial - - - - Qt::Horizontal - - + 0 0 - - - - Arial - - Qt::LeftToRight + + Send data + + + + 0 + 0 + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + + Arial + 18 + 75 + true + - - - - localhost - - - - - - - - - - 0 - 0 - - - - - 0 - 40 - - - - - Arial - 18 - 75 - true - - - - color:#29967e - - - Audio - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - - - 0 - 0 - - - - - 0 - 40 - - - - - 0 - 40 - - - - - Arial - - - - Enable Dynamic Jitter Buffers - - - - - - - 0 - - - 7 - - - 0 - - - 7 - - - - - - Arial - + color:#29967e - Static Jitter Buffer Frames + Avatar tuning - - 0 - - - staticDesiredJitterBufferFramesSpin + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - Arial - + + + 0 + + 7 + + + 0 + + + 7 + + + + + + Arial + + + + + + + Real world vertical field of view (angular size of monitor) + + + 0 + + + fieldOfViewSpin + + + + + + + + Arial + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + + 100 + 0 + + + + + 95 + 36 + + + + + Arial + + + + 1 + + + 180 + + + + + + + + + 0 + + + 7 + + + 0 + + + 7 + + + + + + Arial + + + + + + + Vertical field of view + + + 0 + + + fieldOfViewSpin + + + + + + + + Arial + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + 95 + 36 + + + + + Arial + + + + 1 + + + 180 + + + + + + + + + 0 + + + 8 + + + 8 + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 25 + + + + + Arial + + + + Lean scale (applies to Faceshift users) + + + 0 + + + leanScaleSpin + + + + + + + + Arial + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 40 + 10 + + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + Arial + + + + + + + + + + 0 + + + 7 + + + 0 + + + 7 + + + + + + Arial + + + + Avatar scale <span style=" color:#909090;">(default is 1.0)</span> + + + 0 + + + avatarScaleSpin + + + + + + + + Arial + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 100 + 0 + + + + + 70 + 16777215 + + + + + Arial + + + + + + + + + + 0 + + + 7 + + + 0 + + + 7 + + + + + + Arial + + + + Pupil dillation + + + 0 + + + pupilDilationSlider + + + + + + + + Arial + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 130 + 0 + + + + + Arial + + + + Qt::Horizontal + + + + + + + + + 0 + + + 7 + + + 0 + + + 7 + + + + + + Arial + + + + Faceshift eye detection + + + 0 + + + faceshiftEyeDeflectionSider + + + + + + + + Arial + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 130 + 0 + + + + + Arial + + + + Qt::Horizontal + + + + + + + + + 0 + + + 7 + + + 0 + + + 7 + + + + + + Arial + + + + Faceshift hostname + + + 0 + + + faceshiftHostnameEdit + + + + + + + + Arial + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + + Arial + + + + Qt::LeftToRight + + + + + + localhost + + + + + + + - Qt::Horizontal + Qt::Vertical + + + QSizePolicy::Fixed - 40 + 20 20 - - - - 0 - 0 - - - - - 100 - 0 - - + Arial + 18 + 75 + true - - 0 - - - 10000 - - - 1 - - - - - - - - - 0 - - - 7 - - - 0 - - - 7 - - - - - - Arial - + + color:#29967e - Max Frames Over Desired + Audio - - 0 - - - maxFramesOverDesiredSpin + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - Arial - + + + 7 + + 7 + + + + + + 0 + 40 + + + + + Arial + + + + Enable Dynamic Jitter Buffers + + + + + + + + + 0 + + + 7 + + + 0 + + + 7 + + + + + + Arial + + + + Static Jitter Buffer Frames + + + 0 + + + staticDesiredJitterBufferFramesSpin + + + + + + + + Arial + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + Arial + + + + 0 + + + 10000 + + + 1 + + + + + + + + + 0 + + + 7 + + + 0 + + + 7 + + + + + + Arial + + + + Max Frames Over Desired + + + 0 + + + maxFramesOverDesiredSpin + + + + + + + + Arial + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 100 + 0 + + + + + Arial + + + + 0 + + + 10000 + + + 1 + + + + + + + + + 7 + + + 7 + + + + + + 0 + 32 + + + + + Arial + + + + Use Stdev for Dynamic Jitter Calc + + + + 32 + 32 + + + + + + + + + + 0 + + + 7 + + + 0 + + + 7 + + + + + + Arial + + + + Window A Starve Threshold + + + 0 + + + windowStarveThresholdSpin + + + + + + + + Arial + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + 70 + 16777215 + + + + + Arial + + + + 0 + + + 10000 + + + 1 + + + + + + + + + 0 + + + 7 + + + 0 + + + 7 + + + + + + Arial + + + + Window A (raise desired on N starves) Seconds + + + 0 + + + windowSecondsForDesiredCalcOnTooManyStarvesSpin + + + + + + + + Arial + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + 70 + 16777215 + + + + + Arial + + + + 0 + + + 10000 + + + 1 + + + + + + + + + 0 + + + 7 + + + 0 + + + 7 + + + + + + Arial + + + + Window B (desired ceiling) Seconds + + + 0 + + + windowSecondsForDesiredReductionSpin + + + + + + + + Arial + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + 70 + 16777215 + + + + + Arial + + + + 0 + + + 10000 + + + 1 + + + + + + + + + 7 + + + 7 + + + + + + 0 + 0 + + + + + Arial + + + + Repetition with Fade + + + + 32 + 32 + + + + + + + + + + 0 + + + 7 + + + 0 + + + 7 + + + + + + Arial + + + + Output Buffer Size (Frames) + + + 0 + + + windowSecondsForDesiredReductionSpin + + + + + + + + Arial + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + 70 + 16777215 + + + + + Arial + + + + 1 + + + 20 + + + 1 + + + + + + + + + 7 + + + 7 + + + + + + 0 + 0 + + + + + Arial + + + + Output Starve Detection (Automatic Buffer Size Increase) + + + + 32 + 32 + + + + + + + + + + 0 + + + 7 + + + 0 + + + 7 + + + + + + Arial + + + + Output Starve Detection Threshold + + + 0 + + + windowSecondsForDesiredReductionSpin + + + + + + + + Arial + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + 70 + 16777215 + + + + + Arial + + + + 1 + + + 500 + + + 1 + + + + + + + + + 0 + + + 7 + + + 0 + + + 7 + + + + + + Arial + + + + Output Starve Detection Period (ms) + + + 0 + + + windowSecondsForDesiredReductionSpin + + + + + + + + Arial + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + 70 + 16777215 + + + + + Arial + + + + 1 + + + 999999999 + + + 1 + + + + + + + - Qt::Horizontal + Qt::Vertical + + + QSizePolicy::Fixed - 40 + 20 20 - - - - 100 - 0 - - + Arial + 18 + 75 + true - - 0 - - - 10000 - - - 1 - - - - - - - - - - 0 - 0 - - - - - 0 - 40 - - - - - 0 - 32 - - - - - Arial - - - - Use Stdev for Dynamic Jitter Calc - - - - 32 - 32 - - - - - - - - 0 - - - 7 - - - 0 - - - 7 - - - - - - Arial - + + color:#29967e - Window A Starve Threshold + Octree - - 0 - - - windowStarveThresholdSpin + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - Arial - + + + 0 + + 7 + + + 0 + + + 7 + + + + + + Arial + + + + Max packets sent each second + + + 0 + + + maxOctreePPSSpin + + + + + + + + Arial + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 100 + 0 + + + + + Arial + + + + 60 + + + 6000 + + + 10 + + + + + + + - Qt::Horizontal + Qt::Vertical + + + QSizePolicy::Fixed - 40 + 20 20 - - - - 0 - 0 - - - - - 100 - 0 - - - - - 70 - 16777215 - - + Arial + 18 + 75 + true - - 0 - - - 10000 - - - 1 - - - - - - - - - 0 - - - 7 - - - 0 - - - 7 - - - - - - Arial - + + color:#29967e - Window A (raise desired on N starves) Seconds + Oculus Rift - - 0 - - - windowSecondsForDesiredCalcOnTooManyStarvesSpin + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - Arial - + + + 0 + + 7 + + + 0 + + + 7 + + + + + + Arial + + + + User Interface Angular Size + + + 0 + + + + + + + + Arial + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 100 + 0 + + + + + Arial + + + + 30 + + + 160 + + + 1 + + + 72 + + + + + + + - Qt::Horizontal + Qt::Vertical + + + QSizePolicy::Fixed - 40 + 20 20 - - - - 0 - 0 - - - - - 100 - 0 - - - - - 70 - 16777215 - - + Arial + 18 + 75 + true - - 0 - - - 10000 - - - 1 - - - - - - - - - 0 - - - 7 - - - 0 - - - 7 - - - - - - Arial - + + color:#29967e - Window B (desired ceiling) Seconds + Sixense Controllers - - 0 - - - windowSecondsForDesiredReductionSpin + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - Arial - + + + 7 - - Qt::Horizontal + + 7 - - - 40 - 20 - - - + + + + + 0 + 40 + + + + + Arial + + + + Invert Mouse Buttons + + + + 0 + 0 + + + + + - - - - 0 - 0 - - - - - 100 - 0 - - - - - 70 - 16777215 - - - - - Arial - - - + + 0 - - 10000 + + 7 - - 1 + + 0 - + + 7 + + + + + + Arial + + + + Reticle Movement Speed + + + 0 + + + + + + + + Arial + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 100 + 0 + + + + + Arial + + + + 100 + + + 1 + + + 50 + + + + - - - - - - 0 - 0 - - - - - 32 - 40 - - - - - 0 - 0 - - - - - Arial - - - - Repetition with Fade - - - - 32 - 32 - - - - - - - - 0 - - - 7 - - - 0 - - - 7 - - - - - - Arial - - - - Output Buffer Size (Frames) - - - 0 - - - windowSecondsForDesiredReductionSpin - - - - - - - - Arial - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - - 100 - 0 - - - - - 70 - 16777215 - - - - - Arial - - - - 1 - - - 20 - - - 1 - - - - - - - - - - 0 - 0 - - - - - 32 - 40 - - - - - 0 - 0 - - - - - Arial - - - - Output Starve Detection (Automatic Buffer Size Increase) - - - - 32 - 32 - - - - - - - - 0 - - - 7 - - - 0 - - - 7 - - - - - - Arial - - - - Output Starve Detection Threshold - - - 0 - - - windowSecondsForDesiredReductionSpin - - - - - - - - Arial - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - - 100 - 0 - - - - - 70 - 16777215 - - - - - Arial - - - - 1 - - - 500 - - - 1 - - - - - - - - - 0 - - - 7 - - - 0 - - - 7 - - - - - - Arial - - - - Output Starve Detection Period (ms) - - - 0 - - - windowSecondsForDesiredReductionSpin - - - - - - - - Arial - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - - 100 - 0 - - - - - 70 - 16777215 - - - - - Arial - - - - 1 - - - 999999999 - - - 1 - - - - - - - - - - 0 - 0 - - - - - 0 - 40 - - - - - Arial - 18 - 75 - true - - - - color:#29967e - - - Octree - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - - 0 - - - 7 - - - 0 - - - 7 - - - - - - Arial - - - - Max packets sent each second - - - 0 - - - maxOctreePPSSpin - - - - - - - - Arial - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 100 - 0 - - - - - Arial - - - - 60 - - - 6000 - - - 10 - - - - - - - - - - 0 - 0 - - - - - 0 - 40 - - - - - Arial - 18 - 75 - true - - - - color:#29967e - - - Oculus Rift - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - - 0 - - - 7 - - - 0 - - - 7 - - - - - - Arial - - - - User Interface Angular Size - - - 0 - - - - - - - - Arial - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 100 - 0 - - - - - Arial - - - - 30 - - - 160 - - - 1 - - - 72 - - - - - - - - - - 0 - 0 - - - - - 0 - 40 - - - - - Arial - 18 - 75 - true - - - - color:#29967e - - - Sixense Controllers - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - - - 0 - 35 - - - - - 0 - 40 - - - - - Arial - - - - Invert Mouse Buttons - - - - 0 - 0 - - - - - - - - 0 - - - 7 - - - 0 - - - 7 - - - - - - Arial - - - - Reticle Movement Speed - - - 0 - - - - - - - - Arial - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 100 - 0 - - - - - Arial - - - - 100 - - - 1 - - - 50 - - - - - - - - - - - - 0 - 490 - 501 - 50 - - - - QFrame::NoFrame - - - QFrame::Raised - - - - - 0 - 0 - 491 - 41 - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - Arial - - - - Cancel - - - false - - - - - - - - Arial - - - - Save all changes - - - true - - - false - - - - - - + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + Arial + + + + Cancel + + + false + + + + + + + + Arial + + + + Save all changes + + + true + + + false + + + + + + + + + From 4b3183d820b5cf9eddcffda9724f0a3c7cba42d3 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 19 Feb 2015 17:44:06 -0800 Subject: [PATCH 29/56] AssignmentClients accept an id on the command-line. AssignmentClientMonitor now has a NodeList. It stores its local port in shared memory, like the DomainServer does. As it spawns children, it addes Nodes to the NodeList for each one. The children send status updates to the Monitor. The Monitor will notice if there are no spares and fork another child. --- assignment-client/src/AssignmentClient.cpp | 77 +++++++--- assignment-client/src/AssignmentClient.h | 12 +- assignment-client/src/AssignmentClientApp.cpp | 84 ++++++++++ assignment-client/src/AssignmentClientApp.h | 19 +++ .../src/AssignmentClientMonitor.cpp | 143 +++++++++++++++++- .../src/AssignmentClientMonitor.h | 21 ++- assignment-client/src/main.cpp | 30 +--- domain-server/src/DomainServer.cpp | 16 +- libraries/networking/src/LimitedNodeList.cpp | 38 +++++ libraries/networking/src/LimitedNodeList.h | 10 ++ libraries/networking/src/NodeList.cpp | 8 +- libraries/networking/src/NodeList.h | 1 + libraries/networking/src/PacketHeaders.cpp | 3 + libraries/networking/src/PacketHeaders.h | 4 +- 14 files changed, 389 insertions(+), 77 deletions(-) create mode 100644 assignment-client/src/AssignmentClientApp.cpp create mode 100644 assignment-client/src/AssignmentClientApp.h diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index bf67d4d597..9098a258e7 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -40,10 +41,11 @@ SharedAssignmentPointer AssignmentClient::_currentAssignment; int hifiSockAddrMeta = qRegisterMetaType("HifiSockAddr"); -AssignmentClient::AssignmentClient(int &argc, char **argv) : +AssignmentClient::AssignmentClient(int &argc, char **argv, QUuid nodeUUID) : QCoreApplication(argc, argv), _assignmentServerHostname(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME), - _localASPortSharedMem(NULL) + _localASPortSharedMem(NULL), + _localACMPortSharedMem(NULL) { LogUtils::init(); @@ -57,6 +59,8 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : auto addressManager = DependencyManager::set(); auto nodeList = DependencyManager::set(NodeType::Unassigned); auto avatarHashMap = DependencyManager::set(); + + nodeList->setSessionUUID(nodeUUID); // setup a shutdown event listener to handle SIGTERM or WM_CLOSE for us #ifdef _WIN32 @@ -123,9 +127,8 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : // call a timer function every ASSIGNMENT_REQUEST_INTERVAL_MSECS to ask for assignment, if required qDebug() << "Waiting for assignment -" << _requestAssignment; - QTimer* timer = new QTimer(this); - connect(timer, SIGNAL(timeout()), SLOT(sendAssignmentRequest())); - timer->start(ASSIGNMENT_REQUEST_INTERVAL_MSECS); + connect(&_requestTimer, SIGNAL(timeout()), SLOT(sendAssignmentRequest())); + _requestTimer.start(ASSIGNMENT_REQUEST_INTERVAL_MSECS); // connect our readPendingDatagrams method to the readyRead() signal of the socket connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClient::readPendingDatagrams); @@ -136,6 +139,36 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : // Create Singleton objects on main thread NetworkAccessManager::getInstance(); + + setUpStatsToMonitor(); +} + + +void AssignmentClient::setUpStatsToMonitor() { + // Figure out the address to send out stats to + quint16 localMonitorServerPort = DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT; + auto nodeList = DependencyManager::get(); + + nodeList->getLocalPortFromSharedMemory(ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY, + _localACMPortSharedMem, localMonitorServerPort); + _assignmentClientMonitorSocket = HifiSockAddr(DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME, localMonitorServerPort, true); + + // send a stats packet every 1 seconds + connect(&_statsTimerACM, &QTimer::timeout, this, &AssignmentClient::sendStatsPacketToACM); + _statsTimerACM.start(1000); +} + +void AssignmentClient::sendStatsPacketToACM() { + // tell the assignment client monitor what this assignment client is doing (if anything) + QJsonObject statsObject; + auto nodeList = DependencyManager::get(); + + if (_currentAssignment) { + statsObject["assignment_type"] = _currentAssignment->getTypeName(); + } else { + statsObject["assignment_type"] = "none"; + } + nodeList->sendStats(statsObject, _assignmentClientMonitorSocket); } void AssignmentClient::sendAssignmentRequest() { @@ -145,34 +178,22 @@ void AssignmentClient::sendAssignmentRequest() { if (_assignmentServerHostname == "localhost") { // we want to check again for the local domain-server port in case the DS has restarted - if (!_localASPortSharedMem) { - _localASPortSharedMem = new QSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this); - - if (!_localASPortSharedMem->attach(QSharedMemory::ReadOnly)) { - qWarning() << "Could not attach to shared memory at key" << DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY - << "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort(); - } - } - - if (_localASPortSharedMem->isAttached()) { - _localASPortSharedMem->lock(); - - quint16 localAssignmentServerPort; - memcpy(&localAssignmentServerPort, _localASPortSharedMem->data(), sizeof(localAssignmentServerPort)); - - _localASPortSharedMem->unlock(); - + quint16 localAssignmentServerPort; + if (nodeList->getLocalPortFromSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, _localASPortSharedMem, + localAssignmentServerPort)) { if (localAssignmentServerPort != _assignmentServerSocket.getPort()) { qDebug() << "Port for local assignment server read from shared memory is" - << localAssignmentServerPort; + << localAssignmentServerPort; _assignmentServerSocket.setPort(localAssignmentServerPort); nodeList->setAssignmentServerSocket(_assignmentServerSocket); } } - + else { + qDebug () << "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort(); + } } - + nodeList->sendAssignment(_requestAssignment); } } @@ -227,10 +248,16 @@ void AssignmentClient::readPendingDatagrams() { } else { qDebug() << "Received an assignment that could not be unpacked. Re-requesting."; } + } else if (packetTypeForPacket(receivedPacket) == PacketTypeStopNode) { + qDebug() << "Network told me to exit"; + quit(); } else { + qDebug() << "punt"; // have the NodeList attempt to handle it nodeList->processNodeData(senderSockAddr, receivedPacket); } + } else { + qDebug() << "packetVersionAndHashMatch said no"; } } } diff --git a/assignment-client/src/AssignmentClient.h b/assignment-client/src/AssignmentClient.h index 053458f136..7f0f16e6d6 100644 --- a/assignment-client/src/AssignmentClient.h +++ b/assignment-client/src/AssignmentClient.h @@ -21,7 +21,7 @@ class QSharedMemory; class AssignmentClient : public QCoreApplication { Q_OBJECT public: - AssignmentClient(int &argc, char **argv); + AssignmentClient(int &argc, char **argv, QUuid nodeUUID); static const SharedAssignmentPointer& getCurrentAssignment() { return _currentAssignment; } private slots: @@ -29,13 +29,21 @@ private slots: void readPendingDatagrams(); void assignmentCompleted(); void handleAuthenticationRequest(); + void sendStatsPacketToACM(); private: + void setUpStatsToMonitor(); Assignment _requestAssignment; static SharedAssignmentPointer _currentAssignment; QString _assignmentServerHostname; HifiSockAddr _assignmentServerSocket; - QSharedMemory* _localASPortSharedMem; + QSharedMemory* _localASPortSharedMem; // memory shared with domain server + QSharedMemory* _localACMPortSharedMem; // memory shared with assignment client monitor + QTimer _requestTimer; // timer for requesting and assignment + QTimer _statsTimerACM; // timer for sending stats to assignment client monitor + + protected: + HifiSockAddr _assignmentClientMonitorSocket; }; #endif // hifi_AssignmentClient_h diff --git a/assignment-client/src/AssignmentClientApp.cpp b/assignment-client/src/AssignmentClientApp.cpp new file mode 100644 index 0000000000..4541732e2c --- /dev/null +++ b/assignment-client/src/AssignmentClientApp.cpp @@ -0,0 +1,84 @@ +// +// AssignmentClientapp.cpp +// assignment-client/src +// +// Created by Seth Alves on 2/19/15. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include + +#include +#include + +#include "Assignment.h" +#include "AssignmentClient.h" +#include "AssignmentClientMonitor.h" +#include "AssignmentClientApp.h" + + +AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : + QApplication(argc, argv) +{ +# ifndef WIN32 + setvbuf(stdout, NULL, _IOLBF, 0); +# endif + + // use the verbose message handler in Logging + qInstallMessageHandler(LogHandler::verboseMessageHandler); + + // parse command-line + QCommandLineParser parser; + parser.setApplicationDescription("High Fidelity Assignment Client"); + parser.addHelpOption(); + + const QCommandLineOption helpOption = parser.addHelpOption(); + + const QCommandLineOption numChildsOption("n", "number of children to fork", "child-count"); + parser.addOption(numChildsOption); + + const QCommandLineOption idOption("i", "assignment client id", "uuid"); + parser.addOption(idOption); + + if (!parser.parse(QCoreApplication::arguments())) { + qCritical() << parser.errorText() << endl; + parser.showHelp(); + Q_UNREACHABLE(); + } + + if (parser.isSet(helpOption)) { + parser.showHelp(); + Q_UNREACHABLE(); + } + + if (parser.isSet(numChildsOption) && parser.isSet(idOption)) { + qCritical() << "using both -i and -n doesn't make sense."; + parser.showHelp(); + Q_UNREACHABLE(); + } + + unsigned int numForks = 0; + if (parser.isSet(numChildsOption)) { + numForks = parser.value(numChildsOption).toInt(); + } + + QUuid nodeUUID = QUuid::createUuid(); + if (parser.isSet(idOption)) { + nodeUUID = QUuid(parser.value(idOption)); + } + + if (numForks) { + AssignmentClientMonitor monitor(argc, argv, numForks); + monitor.exec(); + } else { + AssignmentClient client(argc, argv, nodeUUID); + client.exec(); + } +} + + +AssignmentClientApp::~AssignmentClientApp() { +} diff --git a/assignment-client/src/AssignmentClientApp.h b/assignment-client/src/AssignmentClientApp.h new file mode 100644 index 0000000000..6c91fa06a3 --- /dev/null +++ b/assignment-client/src/AssignmentClientApp.h @@ -0,0 +1,19 @@ +// +// AssignmentClientapp.h +// assignment-client/src +// +// Created by Seth Alves on 2/19/15. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include + +class AssignmentClientApp : public QApplication { + Q_OBJECT +public: + AssignmentClientApp(int argc, char* argv[]); + ~AssignmentClientApp(); +}; diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 45e1f56d53..831d50c134 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -14,13 +14,18 @@ #include #include + +#include // XXX need this? + + #include "AssignmentClientMonitor.h" +#include "PacketHeaders.h" const char* NUM_FORKS_PARAMETER = "-n"; const QString ASSIGNMENT_CLIENT_MONITOR_TARGET_NAME = "assignment-client-monitor"; -AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, int numAssignmentClientForks) : +AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, const unsigned int numAssignmentClientForks) : QCoreApplication(argc, argv) { // start the Logging class with the parent's target name @@ -41,17 +46,38 @@ AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, int num // this removes both the "-n" parameter and the number of forks passed _childArguments.removeAt(forksParameterIndex); _childArguments.removeAt(forksParameterIndex); + + + // create a NodeList so we can receive stats from children + DependencyManager::registerInheritance(); + auto addressManager = DependencyManager::set(); + // auto nodeList = DependencyManager::set(NodeType::Unassigned); + auto nodeList = DependencyManager::set(DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT, + DEFAULT_ASSIGNMENT_CLIENT_MONITOR_DTLS_PORT); + + connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClientMonitor::readPendingDatagrams); + + nodeList->putLocalPortIntoSharedMemory(ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY, this); // use QProcess to fork off a process for each of the child assignment clients - for (int i = 0; i < numAssignmentClientForks; i++) { + for (unsigned int i = 0; i < numAssignmentClientForks; i++) { spawnChildClient(); } + + connect(&_checkSparesTimer, SIGNAL(timeout()), SLOT(checkSpares())); + _checkSparesTimer.start(5000); } AssignmentClientMonitor::~AssignmentClientMonitor() { stopChildProcesses(); + + foreach (AssignmentClientChildData* childStatus, _childStatus) { + delete childStatus; + } } + + void AssignmentClientMonitor::stopChildProcesses() { QList >::Iterator it = _childProcesses.begin(); @@ -74,11 +100,18 @@ void AssignmentClientMonitor::spawnChildClient() { QProcess *assignmentClient = new QProcess(this); _childProcesses.append(QPointer(assignmentClient)); + + QUuid childUUID = QUuid::createUuid(); + + // create a Node for this child. this is done so we can idenitfy packets from unknown children + DependencyManager::get()->addOrUpdateNode + (childUUID, NodeType::Unassigned, HifiSockAddr("localhost", 0), HifiSockAddr("localhost", 0), false); // make sure that the output from the child process appears in our output assignmentClient->setProcessChannelMode(QProcess::ForwardedChannels); - - assignmentClient->start(applicationFilePath(), _childArguments); + + QStringList idArgs = QStringList() << "-i" << childUUID.toString(); + assignmentClient->start(applicationFilePath(), _childArguments + idArgs); // link the child processes' finished slot to our childProcessFinished slot connect(assignmentClient, SIGNAL(finished(int, QProcess::ExitStatus)), this, @@ -96,3 +129,105 @@ void AssignmentClientMonitor::childProcessFinished(int exitCode, QProcess::ExitS spawnChildClient(); } + + + +void AssignmentClientMonitor::checkSpares() { + qDebug() << "check spares:"; + + QString aSpareId = ""; + unsigned int spareCount = 0; + + QHash::const_iterator i = _childStatus.constBegin(); + while (i != _childStatus.constEnd()) { + qDebug() << " " << i.key() << i.value()->getChildType(); + if (i.value()->getChildType() == "none") { + spareCount ++; + aSpareId = i.key(); + } + ++i; + } + + qDebug() << "spare count is" << spareCount; + + if (spareCount < 1) { + qDebug() << "FORK"; + spawnChildClient(); + } + + if (spareCount > 1) { + qDebug() << "KILL"; + } +} + + + + +void AssignmentClientMonitor::readPendingDatagrams() { + auto nodeList = DependencyManager::get(); + + QByteArray receivedPacket; + HifiSockAddr senderSockAddr; + + while (nodeList->getNodeSocket().hasPendingDatagrams()) { + receivedPacket.resize(nodeList->getNodeSocket().pendingDatagramSize()); + nodeList->getNodeSocket().readDatagram(receivedPacket.data(), receivedPacket.size(), + senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer()); + + if (nodeList->packetVersionAndHashMatch(receivedPacket)) { + if (packetTypeForPacket(receivedPacket) == PacketTypeNodeJsonStats) { + + QUuid packetUUID = uuidFromPacketHeader(receivedPacket); + // qDebug() << "packetUUID = " << packetUUID; + + SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(receivedPacket); + if (!matchingNode) { + qDebug() << "got packet from unknown child, id =" << packetUUID.toString(); + // tell unknown assignment-client child to exit. + QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); + nodeList->writeUnverifiedDatagram(diePacket, senderSockAddr); + } + + if (matchingNode) { + // update our records about how to reach this child + matchingNode->setLocalSocket(senderSockAddr); + + // push past the packet header + QDataStream packetStream(receivedPacket); + packetStream.skipRawData(numBytesForPacketHeader(receivedPacket)); + + QVariantMap unpackedVariantMap; + + packetStream >> unpackedVariantMap; + + QJsonObject unpackedStatsJSON = QJsonObject::fromVariantMap(unpackedVariantMap); + + // qDebug() << "ACM got stats packet, id =" << packetUUID.toString() + // << "type =" << unpackedStatsJSON["assignment_type"]; + + QString key(QString(packetUUID.toString())); + if (_childStatus.contains(key)) { + delete _childStatus[ key ]; + } + + QString childType = unpackedStatsJSON["assignment_type"].toString(); + auto childStatus = new AssignmentClientChildData(childType); + _childStatus[ key ] = childStatus; + + } + } else { + // have the NodeList attempt to handle it + nodeList->processNodeData(senderSockAddr, receivedPacket); + } + } + } +} + + +AssignmentClientChildData::AssignmentClientChildData(QString childType) { + _childType = childType; +} + + +AssignmentClientChildData::~AssignmentClientChildData() { +} diff --git a/assignment-client/src/AssignmentClientMonitor.h b/assignment-client/src/AssignmentClientMonitor.h index 9a7bca9cb3..75d2296533 100644 --- a/assignment-client/src/AssignmentClientMonitor.h +++ b/assignment-client/src/AssignmentClientMonitor.h @@ -20,20 +20,39 @@ extern const char* NUM_FORKS_PARAMETER; +class AssignmentClientChildData { + public: + AssignmentClientChildData(QString childType); + ~AssignmentClientChildData(); + + QString getChildType() { return _childType; } + + private: + QString _childType; + // ... timestamp +}; + + class AssignmentClientMonitor : public QCoreApplication { Q_OBJECT public: - AssignmentClientMonitor(int &argc, char **argv, int numAssignmentClientForks); + AssignmentClientMonitor(int &argc, char **argv, const unsigned int numAssignmentClientForks); ~AssignmentClientMonitor(); void stopChildProcesses(); private slots: void childProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); + void readPendingDatagrams(); + void checkSpares(); + private: void spawnChildClient(); QList > _childProcesses; QStringList _childArguments; + QHash _childStatus; + + QTimer _checkSparesTimer; // every few seconds see if it need fewer or more spare children }; #endif // hifi_AssignmentClientMonitor_h diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index 3bf6990a74..81a12526bf 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -9,34 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include -#include -#include "Assignment.h" -#include "AssignmentClient.h" -#include "AssignmentClientMonitor.h" +#include "AssignmentClientApp.h" int main(int argc, char* argv[]) { -#ifndef WIN32 - setvbuf(stdout, NULL, _IOLBF, 0); -#endif - - // use the verbose message handler in Logging - qInstallMessageHandler(LogHandler::verboseMessageHandler); - - const char* numForksString = getCmdOption(argc, (const char**)argv, NUM_FORKS_PARAMETER); - - int numForks = 0; - - if (numForksString) { - numForks = atoi(numForksString); - } - - if (numForks) { - AssignmentClientMonitor monitor(argc, argv, numForks); - return monitor.exec(); - } else { - AssignmentClient client(argc, argv); - return client.exec(); - } + AssignmentClientApp app(argc, argv); + return 0; } diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index f84722a438..30d6dd4348 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -244,21 +244,9 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) { populateStaticScriptedAssignmentsFromSettings(); auto nodeList = DependencyManager::set(domainServerPort, domainServerDTLSPort); - + // no matter the local port, save it to shared mem so that local assignment clients can ask what it is - QSharedMemory* sharedPortMem = new QSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this); - quint16 localPort = nodeList->getNodeSocket().localPort(); - - // attempt to create the shared memory segment - if (sharedPortMem->create(sizeof(localPort)) || sharedPortMem->attach()) { - sharedPortMem->lock(); - memcpy(sharedPortMem->data(), &localPort, sizeof(localPort)); - sharedPortMem->unlock(); - - qDebug() << "Wrote local listening port" << localPort << "to shared memory at key" << DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY; - } else { - qWarning() << "Failed to create and attach to shared memory to share local port with assignment-client children."; - } + nodeList->putLocalPortIntoSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this); // set our LimitedNodeList UUID to match the UUID from our config // nodes will currently use this to add resources to data-web that relate to our domain diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index c8c454ff14..075fd5a44b 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -669,3 +669,41 @@ void LimitedNodeList::sendHeartbeatToIceServer(const HifiSockAddr& iceServerSock writeUnverifiedDatagram(iceRequestByteArray, iceServerSockAddr); } + +void LimitedNodeList::putLocalPortIntoSharedMemory(const QString key, QObject* parent) { + // save our local port to shared memory so that assignment client children know how to talk to this parent + QSharedMemory* sharedPortMem = new QSharedMemory(key, parent); + quint16 localPort = getNodeSocket().localPort(); + + // attempt to create the shared memory segment + if (sharedPortMem->create(sizeof(localPort)) || sharedPortMem->attach()) { + sharedPortMem->lock(); + memcpy(sharedPortMem->data(), &localPort, sizeof(localPort)); + sharedPortMem->unlock(); + + qDebug() << "Wrote local listening port" << localPort << "to shared memory at key" << key; + } else { + qWarning() << "Failed to create and attach to shared memory to share local port with assignment-client children."; + } +} + + +bool LimitedNodeList::getLocalPortFromSharedMemory(const QString key, QSharedMemory* &sharedMem, + quint16& localPort) { + if (!sharedMem) { + sharedMem = new QSharedMemory(key, this); + + if (!sharedMem->attach(QSharedMemory::ReadOnly)) { + qWarning() << "Could not attach to shared memory at key" << key; + } + } + + if (sharedMem->isAttached()) { + sharedMem->lock(); + memcpy(&localPort, sharedMem->data(), sizeof(localPort)); + sharedMem->unlock(); + return true; + } + + return false; +} diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 72aefdb2b3..e7ccbe7746 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -25,6 +25,8 @@ #include #include #include +#include + #include #include @@ -49,6 +51,11 @@ const char STUN_SERVER_HOSTNAME[] = "stun.highfidelity.io"; const unsigned short STUN_SERVER_PORT = 3478; const QString DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY = "domain-server.local-port"; +const QString ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY = "assignment-client-monitor.local-port"; + +const char DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME[] = "localhost"; +const unsigned short DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT = 40104; +const unsigned short DEFAULT_ASSIGNMENT_CLIENT_MONITOR_DTLS_PORT = 40105; class HifiSockAddr; @@ -168,6 +175,9 @@ public: return SharedNodePointer(); } + + void putLocalPortIntoSharedMemory(const QString key, QObject* parent); + bool getLocalPortFromSharedMemory(const QString key, QSharedMemory* &sharedMem, quint16& localPort); public slots: void reset(); diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index f70c2d9b3c..e63f230f6e 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -62,13 +62,17 @@ NodeList::NodeList(char newOwnerType, unsigned short socketListenPort, unsigned connect(&AccountManager::getInstance(), &AccountManager::logoutComplete , this, &NodeList::reset); } -qint64 NodeList::sendStatsToDomainServer(const QJsonObject& statsObject) { +qint64 NodeList::sendStats(const QJsonObject& statsObject, HifiSockAddr destination) { QByteArray statsPacket = byteArrayWithPopulatedHeader(PacketTypeNodeJsonStats); QDataStream statsPacketStream(&statsPacket, QIODevice::Append); statsPacketStream << statsObject.toVariantMap(); - return writeUnverifiedDatagram(statsPacket, _domainHandler.getSockAddr()); + return writeUnverifiedDatagram(statsPacket, destination); +} + +qint64 NodeList::sendStatsToDomainServer(const QJsonObject& statsObject) { + return sendStats(statsObject, _domainHandler.getSockAddr()); } void NodeList::timePingReply(const QByteArray& packet, const SharedNodePointer& sendingNode) { diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index 907fccfcac..1c6de4bb6c 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -47,6 +47,7 @@ public: NodeType_t getOwnerType() const { return _ownerType; } void setOwnerType(NodeType_t ownerType) { _ownerType = ownerType; } + qint64 sendStats(const QJsonObject& statsObject, HifiSockAddr destination); qint64 sendStatsToDomainServer(const QJsonObject& statsObject); int getNumNoReplyDomainCheckIns() const { return _numNoReplyDomainCheckIns; } diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index 2eee540fff..db97e216ee 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -70,6 +70,8 @@ PacketVersion versionForPacketType(PacketType type) { return 2; case PacketTypeOctreeStats: return 1; + case PacketTypeStopNode: + return 1; case PacketTypeEntityAddOrEdit: case PacketTypeEntityData: return VERSION_MODEL_ENTITIES_SUPPORT_SHAPE_TYPE; @@ -124,6 +126,7 @@ QString nameForPacketType(PacketType type) { PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityErase); PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityAddResponse); PACKET_TYPE_NAME_LOOKUP(PacketTypeOctreeDataNack); + PACKET_TYPE_NAME_LOOKUP(PacketTypeStopNode); PACKET_TYPE_NAME_LOOKUP(PacketTypeAudioEnvironment); PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityEditNack); PACKET_TYPE_NAME_LOOKUP(PacketTypeSignedTransactionPayment); diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index e593955b51..32f33c01d9 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -67,7 +67,7 @@ enum PacketType { PacketTypeEntityErase, PacketTypeEntityAddResponse, PacketTypeOctreeDataNack, // 45 - UNUSED_10, + PacketTypeStopNode, PacketTypeAudioEnvironment, PacketTypeEntityEditNack, PacketTypeSignedTransactionPayment, @@ -86,7 +86,7 @@ const QSet NON_VERIFIED_PACKETS = QSet() << PacketTypeNodeJsonStats << PacketTypeEntityQuery << PacketTypeOctreeDataNack << PacketTypeEntityEditNack << PacketTypeIceServerHeartbeat << PacketTypeIceServerHeartbeatResponse - << PacketTypeUnverifiedPing << PacketTypeUnverifiedPingReply; + << PacketTypeUnverifiedPing << PacketTypeUnverifiedPingReply << PacketTypeStopNode; const int NUM_BYTES_MD5_HASH = 16; const int NUM_STATIC_HEADER_BYTES = sizeof(PacketVersion) + NUM_BYTES_RFC4122_UUID; From 599ef68df80d00dd816f2ad41e8a68568c6cca94 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 20 Feb 2015 08:26:11 -0800 Subject: [PATCH 30/56] fix for scratchy audio on windows --- interface/src/audio/AudioScope.h | 2 +- libraries/audio-client/src/AudioClient.cpp | 21 +++++++++------------ libraries/audio-client/src/AudioClient.h | 14 ++++++++++++-- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/interface/src/audio/AudioScope.h b/interface/src/audio/AudioScope.h index df902fe7cd..cc9367e2d5 100644 --- a/interface/src/audio/AudioScope.h +++ b/interface/src/audio/AudioScope.h @@ -75,4 +75,4 @@ private: }; -#endif // hifi_AudioScope_h \ No newline at end of file +#endif // hifi_AudioScope_h diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index b427d5ba42..49dd1e1a35 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -85,16 +85,9 @@ AudioClient::AudioClient() : _isStereoInput(false), _outputStarveDetectionStartTimeMsec(0), _outputStarveDetectionCount(0), - _outputBufferSizeFrames("audioOutputBufferSize", - DEFAULT_MAX_FRAMES_OVER_DESIRED), -#ifdef Q_OS_ANDROID - _outputStarveDetectionEnabled("audioOutputStarveDetectionEnabled", - false), -#else + _outputBufferSizeFrames("audioOutputBufferSize", DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES), _outputStarveDetectionEnabled("audioOutputStarveDetectionEnabled", DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_ENABLED), -#endif - _outputStarveDetectionPeriodMsec("audioOutputStarveDetectionPeriod", DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_PERIOD), _outputStarveDetectionThreshold("audioOutputStarveDetectionThreshold", @@ -1089,12 +1082,16 @@ void AudioClient::outputNotify() { } else { _outputStarveDetectionCount += recentUnfulfilled; if (_outputStarveDetectionCount > _outputStarveDetectionThreshold.get()) { - int newOutputBufferSizeFrames = _outputBufferSizeFrames.get() + 1; - qDebug() << "Starve detection threshold met, increasing buffer size to " << newOutputBufferSizeFrames; - setOutputBufferSize(newOutputBufferSizeFrames); - _outputStarveDetectionStartTimeMsec = now; _outputStarveDetectionCount = 0; + + int oldOutputBufferSizeFrames = _outputBufferSizeFrames.get(); + int newOutputBufferSizeFrames = oldOutputBufferSizeFrames + 1; + setOutputBufferSize(newOutputBufferSizeFrames); + newOutputBufferSizeFrames = _outputBufferSizeFrames.get(); + if (newOutputBufferSizeFrames > oldOutputBufferSizeFrames) { + qDebug() << "Starve detection threshold met, increasing buffer size to " << newOutputBufferSizeFrames; + } } } } diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index 0095a885eb..811282c0a1 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -56,8 +56,18 @@ static const int NUM_AUDIO_CHANNELS = 2; static const int DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 3; static const int MIN_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 1; -static const int MAX_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 20; -static const int DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_ENABLED = true; +#ifdef _WIN32 + // WORKAROUND: Some sound devices on Windows (at least 8.1) will get scratchy if their output + // buffer is set too high so we have to limit the number of frames in the buffer. + static const int MAX_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 5; +#else + static const int MAX_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 20; +#endif +#ifdef Q_OS_ANDROID + static const int DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_ENABLED = false; +#else + static const int DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_ENABLED = true; +#endif static const int DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_THRESHOLD = 3; static const quint64 DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_PERIOD = 10 * 1000; // 10 Seconds From c3dbae1bd3488cc802c5beac88a211923ba51d64 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 20 Feb 2015 09:00:28 -0800 Subject: [PATCH 31/56] remove warning about signed-unsigned comparison --- libraries/audio-client/src/AudioClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index f7777c26a2..6e068e0635 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -1083,7 +1083,7 @@ void AudioClient::outputNotify() { if (recentUnfulfilled > 0) { if (_outputStarveDetectionEnabled.get()) { quint64 now = usecTimestampNow() / 1000; - quint64 dt = now - _outputStarveDetectionStartTimeMsec; + int dt = (int)(now - _outputStarveDetectionStartTimeMsec); if (dt > _outputStarveDetectionPeriodMsec.get()) { _outputStarveDetectionStartTimeMsec = now; _outputStarveDetectionCount = 0; From 5c3cae471be2e0527abfe8eea8ca8a84193c8a6f Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 20 Feb 2015 09:48:04 -0800 Subject: [PATCH 32/56] Fix avatar billboards all rendering as the same billboard --- interface/src/avatar/Avatar.cpp | 21 +++++++++------------ interface/src/avatar/Avatar.h | 2 +- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index d4c10b2b4a..6dc3d4b339 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -537,18 +537,13 @@ void Avatar::renderBillboard() { return; } if (!_billboardTexture) { - QImage image = QImage::fromData(_billboard); - if (image.format() != QImage::Format_ARGB32) { - image = image.convertToFormat(QImage::Format_ARGB32); - } - _billboardTexture.reset(new Texture()); - glBindTexture(GL_TEXTURE_2D, _billboardTexture->getID()); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, - GL_BGRA, GL_UNSIGNED_BYTE, image.constBits()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - } else { - glBindTexture(GL_TEXTURE_2D, _billboardTexture->getID()); + // Using a unique URL ensures we don't get another avatar's texture from TextureCache + QUrl uniqueUrl = QUrl(QUuid::createUuid().toString()); + _billboardTexture = DependencyManager::get()->getTexture( + uniqueUrl, DEFAULT_TEXTURE, false, _billboard); + } + if (!_billboardTexture->isLoaded()) { + return; } glEnable(GL_ALPHA_TEST); @@ -556,6 +551,8 @@ void Avatar::renderBillboard() { glEnable(GL_TEXTURE_2D); glDisable(GL_LIGHTING); + + glBindTexture(GL_TEXTURE_2D, _billboardTexture->getID()); glPushMatrix(); glTranslatef(_position.x, _position.y, _position.z); diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 18e42b7dd7..72b7ecf93a 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -234,7 +234,7 @@ protected: private: bool _initialized; - QScopedPointer _billboardTexture; + NetworkTexturePointer _billboardTexture; bool _shouldRenderBillboard; bool _isLookAtTarget; From 94b3c4a3a89623409a6506996a85fd774915068c Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 20 Feb 2015 11:57:37 -0800 Subject: [PATCH 33/56] simpler less draconian workaround --- libraries/audio-client/src/AudioClient.h | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index 941fcc6c12..7ac445a7fc 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -56,14 +56,8 @@ static const int NUM_AUDIO_CHANNELS = 2; static const int DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 3; static const int MIN_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 1; -#ifdef _WIN32 - // WORKAROUND: Some sound devices on Windows (at least 8.1) will get scratchy if their output - // buffer is set too high so we have to limit the number of frames in the buffer. - static const int MAX_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 5; -#else - static const int MAX_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 20; -#endif -#ifdef Q_OS_ANDROID +static const int MAX_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 20; +#if defined(Q_OS_ANDROID) || defined(Q_OS_WIN) static const int DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_ENABLED = false; #else static const int DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_ENABLED = true; From feb0e7ac31a7f6c8950278b35163c01e5079ee64 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 20 Feb 2015 13:26:59 -0800 Subject: [PATCH 34/56] AssignmentClientMonitor doesn't keep a list of its children. Instead it knows about active children due to their entries in the NodeList. Every few seconds, if 2 or more children are idle, the Monitor will ask one to exit --- assignment-client/src/AssignmentClient.cpp | 42 ++++-- assignment-client/src/AssignmentClient.h | 3 +- assignment-client/src/AssignmentClientApp.cpp | 18 +-- assignment-client/src/AssignmentClientApp.h | 2 +- .../src/AssignmentClientMonitor.cpp | 134 +++++++----------- .../src/AssignmentClientMonitor.h | 14 +- libraries/networking/src/AddressManager.cpp | 4 +- 7 files changed, 99 insertions(+), 118 deletions(-) diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 9098a258e7..a0304acad9 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -18,7 +18,7 @@ #include #include #include -#include +// #include #include #include #include @@ -41,7 +41,7 @@ SharedAssignmentPointer AssignmentClient::_currentAssignment; int hifiSockAddrMeta = qRegisterMetaType("HifiSockAddr"); -AssignmentClient::AssignmentClient(int &argc, char **argv, QUuid nodeUUID) : +AssignmentClient::AssignmentClient(int &argc, char **argv) : QCoreApplication(argc, argv), _assignmentServerHostname(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME), _localASPortSharedMem(NULL), @@ -58,8 +58,11 @@ AssignmentClient::AssignmentClient(int &argc, char **argv, QUuid nodeUUID) : DependencyManager::registerInheritance(); auto addressManager = DependencyManager::set(); auto nodeList = DependencyManager::set(NodeType::Unassigned); - auto avatarHashMap = DependencyManager::set(); + // auto avatarHashMap = DependencyManager::set(); + // make up a uuid for this child so the parent can tell us apart. This id will be changed + // when the domain server hands over an assignment. + QUuid nodeUUID = QUuid::createUuid(); nodeList->setSessionUUID(nodeUUID); // setup a shutdown event listener to handle SIGTERM or WM_CLOSE for us @@ -139,11 +142,37 @@ AssignmentClient::AssignmentClient(int &argc, char **argv, QUuid nodeUUID) : // Create Singleton objects on main thread NetworkAccessManager::getInstance(); + // DependencyManager::get(); setUpStatsToMonitor(); } +void AssignmentClient::stopAssignmentClient() { + + // QList threads = QObject::findChildren (); + // foreach(QThread *thread, threads) { // or FileUploader* fileuploader, fileUploaders_ ? + // qDebug() << "thread " << thread->currentThreadId(); + // } + + qDebug() << "Exiting."; + + _requestTimer.stop(); + _statsTimerACM.stop(); + + + // DependencyManager::get()->disconnect(); + // DependencyManager::get()->disconnectNotify(); + // DependencyManager::get()->disconnect(); + // DependencyManager::get()->disconnectNotify(); + + // DependencyManager::destroy(); + // DependencyManager::destroy(); + + quit(); +} + + void AssignmentClient::setUpStatsToMonitor() { // Figure out the address to send out stats to quint16 localMonitorServerPort = DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT; @@ -249,15 +278,12 @@ void AssignmentClient::readPendingDatagrams() { qDebug() << "Received an assignment that could not be unpacked. Re-requesting."; } } else if (packetTypeForPacket(receivedPacket) == PacketTypeStopNode) { - qDebug() << "Network told me to exit"; - quit(); + qDebug() << "Network told me to exit."; + emit stopAssignmentClient(); } else { - qDebug() << "punt"; // have the NodeList attempt to handle it nodeList->processNodeData(senderSockAddr, receivedPacket); } - } else { - qDebug() << "packetVersionAndHashMatch said no"; } } } diff --git a/assignment-client/src/AssignmentClient.h b/assignment-client/src/AssignmentClient.h index 7f0f16e6d6..e105309e10 100644 --- a/assignment-client/src/AssignmentClient.h +++ b/assignment-client/src/AssignmentClient.h @@ -21,7 +21,7 @@ class QSharedMemory; class AssignmentClient : public QCoreApplication { Q_OBJECT public: - AssignmentClient(int &argc, char **argv, QUuid nodeUUID); + AssignmentClient(int &argc, char **argv); static const SharedAssignmentPointer& getCurrentAssignment() { return _currentAssignment; } private slots: @@ -30,6 +30,7 @@ private slots: void assignmentCompleted(); void handleAuthenticationRequest(); void sendStatsPacketToACM(); + void stopAssignmentClient(); private: void setUpStatsToMonitor(); diff --git a/assignment-client/src/AssignmentClientApp.cpp b/assignment-client/src/AssignmentClientApp.cpp index 4541732e2c..8848b59c49 100644 --- a/assignment-client/src/AssignmentClientApp.cpp +++ b/assignment-client/src/AssignmentClientApp.cpp @@ -21,7 +21,7 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : - QApplication(argc, argv) + QCoreApplication(argc, argv) { # ifndef WIN32 setvbuf(stdout, NULL, _IOLBF, 0); @@ -40,9 +40,6 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : const QCommandLineOption numChildsOption("n", "number of children to fork", "child-count"); parser.addOption(numChildsOption); - const QCommandLineOption idOption("i", "assignment client id", "uuid"); - parser.addOption(idOption); - if (!parser.parse(QCoreApplication::arguments())) { qCritical() << parser.errorText() << endl; parser.showHelp(); @@ -54,27 +51,16 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : Q_UNREACHABLE(); } - if (parser.isSet(numChildsOption) && parser.isSet(idOption)) { - qCritical() << "using both -i and -n doesn't make sense."; - parser.showHelp(); - Q_UNREACHABLE(); - } - unsigned int numForks = 0; if (parser.isSet(numChildsOption)) { numForks = parser.value(numChildsOption).toInt(); } - QUuid nodeUUID = QUuid::createUuid(); - if (parser.isSet(idOption)) { - nodeUUID = QUuid(parser.value(idOption)); - } - if (numForks) { AssignmentClientMonitor monitor(argc, argv, numForks); monitor.exec(); } else { - AssignmentClient client(argc, argv, nodeUUID); + AssignmentClient client(argc, argv); client.exec(); } } diff --git a/assignment-client/src/AssignmentClientApp.h b/assignment-client/src/AssignmentClientApp.h index 6c91fa06a3..09952ad19c 100644 --- a/assignment-client/src/AssignmentClientApp.h +++ b/assignment-client/src/AssignmentClientApp.h @@ -11,7 +11,7 @@ #include -class AssignmentClientApp : public QApplication { +class AssignmentClientApp : public QCoreApplication { Q_OBJECT public: AssignmentClientApp(int argc, char* argv[]); diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 831d50c134..94975b0a4d 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -20,6 +20,7 @@ #include "AssignmentClientMonitor.h" #include "PacketHeaders.h" +#include "SharedUtil.h" const char* NUM_FORKS_PARAMETER = "-n"; @@ -70,85 +71,49 @@ AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, const u AssignmentClientMonitor::~AssignmentClientMonitor() { stopChildProcesses(); - - foreach (AssignmentClientChildData* childStatus, _childStatus) { - delete childStatus; - } } - - void AssignmentClientMonitor::stopChildProcesses() { - - QList >::Iterator it = _childProcesses.begin(); - while (it != _childProcesses.end()) { - if (!it->isNull()) { - qDebug() << "Monitor is terminating child process" << it->data(); - - // don't re-spawn this child when it goes down - disconnect(it->data(), 0, this, 0); - - it->data()->terminate(); - it->data()->waitForFinished(); - } - - it = _childProcesses.erase(it); - } + auto nodeList = DependencyManager::get(); + + nodeList->eachNode([&](const SharedNodePointer& node){ + qDebug() << "asking child" << node->getUUID() << "to exit."; + node->activateLocalSocket(); + QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); + nodeList->writeUnverifiedDatagram(diePacket, *node->getActiveSocket()); + }); } void AssignmentClientMonitor::spawnChildClient() { QProcess *assignmentClient = new QProcess(this); - _childProcesses.append(QPointer(assignmentClient)); - - QUuid childUUID = QUuid::createUuid(); - - // create a Node for this child. this is done so we can idenitfy packets from unknown children - DependencyManager::get()->addOrUpdateNode - (childUUID, NodeType::Unassigned, HifiSockAddr("localhost", 0), HifiSockAddr("localhost", 0), false); - // make sure that the output from the child process appears in our output assignmentClient->setProcessChannelMode(QProcess::ForwardedChannels); - QStringList idArgs = QStringList() << "-i" << childUUID.toString(); - assignmentClient->start(applicationFilePath(), _childArguments + idArgs); - - // link the child processes' finished slot to our childProcessFinished slot - connect(assignmentClient, SIGNAL(finished(int, QProcess::ExitStatus)), this, - SLOT(childProcessFinished(int, QProcess::ExitStatus))); - + assignmentClient->start(applicationFilePath(), _childArguments); qDebug() << "Spawned a child client with PID" << assignmentClient->pid(); } -void AssignmentClientMonitor::childProcessFinished(int exitCode, QProcess::ExitStatus exitStatus) { - qDebug("Replacing dead child assignment client with a new one"); - - // remove the old process from our list of child processes - qDebug() << "need to remove" << QPointer(qobject_cast(sender())); - _childProcesses.removeOne(QPointer(qobject_cast(sender()))); - - spawnChildClient(); -} - - void AssignmentClientMonitor::checkSpares() { - qDebug() << "check spares:"; - - QString aSpareId = ""; + auto nodeList = DependencyManager::get(); + QUuid aSpareId = ""; unsigned int spareCount = 0; - QHash::const_iterator i = _childStatus.constBegin(); - while (i != _childStatus.constEnd()) { - qDebug() << " " << i.key() << i.value()->getChildType(); - if (i.value()->getChildType() == "none") { - spareCount ++; - aSpareId = i.key(); - } - ++i; - } + nodeList->removeSilentNodes(); - qDebug() << "spare count is" << spareCount; + qDebug() << "check spares:"; + + nodeList->eachNode([&](const SharedNodePointer& node){ + AssignmentClientChildData *childData = static_cast(node->getLinkedData()); + qDebug() << " " << node->getUUID() << childData->getChildType(); + if (childData->getChildType() == "none") { + spareCount ++; + aSpareId = node->getUUID(); + } + }); + + qDebug() << " spare count is" << spareCount; if (spareCount < 1) { qDebug() << "FORK"; @@ -156,13 +121,16 @@ void AssignmentClientMonitor::checkSpares() { } if (spareCount > 1) { - qDebug() << "KILL"; + // kill aSpareId + qDebug() << "asking child" << aSpareId << "to exit."; + SharedNodePointer childNode = nodeList->nodeWithUUID(aSpareId); + childNode->activateLocalSocket(); + QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); + nodeList->writeUnverifiedDatagram(diePacket, childNode); } } - - void AssignmentClientMonitor::readPendingDatagrams() { auto nodeList = DependencyManager::get(); @@ -176,16 +144,21 @@ void AssignmentClientMonitor::readPendingDatagrams() { if (nodeList->packetVersionAndHashMatch(receivedPacket)) { if (packetTypeForPacket(receivedPacket) == PacketTypeNodeJsonStats) { - QUuid packetUUID = uuidFromPacketHeader(receivedPacket); - // qDebug() << "packetUUID = " << packetUUID; - SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(receivedPacket); if (!matchingNode) { - qDebug() << "got packet from unknown child, id =" << packetUUID.toString(); - // tell unknown assignment-client child to exit. - QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); - nodeList->writeUnverifiedDatagram(diePacket, senderSockAddr); + // XXX only do this if from local machine + if (!packetUUID.isNull()) { + matchingNode = DependencyManager::get()->addOrUpdateNode + (packetUUID, NodeType::Unassigned, senderSockAddr, senderSockAddr, false); + AssignmentClientChildData *childData = new AssignmentClientChildData("unknown"); + matchingNode->setLinkedData(childData); + } else { + // tell unknown assignment-client child to exit. + qDebug() << "asking unknown child to exit."; + QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); + nodeList->writeUnverifiedDatagram(diePacket, senderSockAddr); + } } if (matchingNode) { @@ -195,25 +168,18 @@ void AssignmentClientMonitor::readPendingDatagrams() { // push past the packet header QDataStream packetStream(receivedPacket); packetStream.skipRawData(numBytesForPacketHeader(receivedPacket)); - + // decode json QVariantMap unpackedVariantMap; - packetStream >> unpackedVariantMap; - QJsonObject unpackedStatsJSON = QJsonObject::fromVariantMap(unpackedVariantMap); - // qDebug() << "ACM got stats packet, id =" << packetUUID.toString() - // << "type =" << unpackedStatsJSON["assignment_type"]; - - QString key(QString(packetUUID.toString())); - if (_childStatus.contains(key)) { - delete _childStatus[ key ]; - } - + // get child's assignment type out of the decoded json QString childType = unpackedStatsJSON["assignment_type"].toString(); - auto childStatus = new AssignmentClientChildData(childType); - _childStatus[ key ] = childStatus; - + AssignmentClientChildData *childData = + static_cast(matchingNode->getLinkedData()); + childData->setChildType(childType); + // note when this child talked + matchingNode->setLastHeardMicrostamp(usecTimestampNow()); } } else { // have the NodeList attempt to handle it diff --git a/assignment-client/src/AssignmentClientMonitor.h b/assignment-client/src/AssignmentClientMonitor.h index 75d2296533..a91dfa93cc 100644 --- a/assignment-client/src/AssignmentClientMonitor.h +++ b/assignment-client/src/AssignmentClientMonitor.h @@ -15,21 +15,25 @@ #include #include #include +#include #include extern const char* NUM_FORKS_PARAMETER; -class AssignmentClientChildData { +class AssignmentClientChildData : public NodeData { public: AssignmentClientChildData(QString childType); ~AssignmentClientChildData(); QString getChildType() { return _childType; } + void setChildType(QString childType) { _childType = childType; } + + // implement parseData to return 0 so we can be a subclass of NodeData + int parseData(const QByteArray& packet) { return 0; } private: QString _childType; - // ... timestamp }; @@ -41,17 +45,15 @@ public: void stopChildProcesses(); private slots: - void childProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); + // void childProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); void readPendingDatagrams(); void checkSpares(); private: void spawnChildClient(); - QList > _childProcesses; + // QList > _childProcesses; QStringList _childArguments; - QHash _childStatus; - QTimer _checkSparesTimer; // every few seconds see if it need fewer or more spare children }; diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 9bcdcbe9a4..f67abdca2b 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -76,7 +76,7 @@ const QString AddressManager::currentPath(bool withOrientation) const { pathString += "/" + orientationString; } else { qDebug() << "Cannot add orientation to path without a getter for position." - << "Call AdressManager::setOrientationGetter to pass a function that will return a glm::quat"; + << "Call AddressManager::setOrientationGetter to pass a function that will return a glm::quat"; } } @@ -84,7 +84,7 @@ const QString AddressManager::currentPath(bool withOrientation) const { return pathString; } else { qDebug() << "Cannot create address path without a getter for position." - << "Call AdressManager::setPositionGetter to pass a function that will return a const glm::vec3&"; + << "Call AddressManager::setPositionGetter to pass a function that will return a const glm::vec3&"; return QString(); } } From 56d237ae8bdaa7df60785b7538ddd42e36cfd8e0 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 20 Feb 2015 13:28:24 -0800 Subject: [PATCH 35/56] cleanups --- assignment-client/src/AssignmentClient.cpp | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index a0304acad9..f0461663a7 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -18,7 +18,6 @@ #include #include #include -// #include #include #include #include @@ -149,26 +148,9 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : void AssignmentClient::stopAssignmentClient() { - - // QList threads = QObject::findChildren (); - // foreach(QThread *thread, threads) { // or FileUploader* fileuploader, fileUploaders_ ? - // qDebug() << "thread " << thread->currentThreadId(); - // } - qDebug() << "Exiting."; - _requestTimer.stop(); _statsTimerACM.stop(); - - - // DependencyManager::get()->disconnect(); - // DependencyManager::get()->disconnectNotify(); - // DependencyManager::get()->disconnect(); - // DependencyManager::get()->disconnectNotify(); - - // DependencyManager::destroy(); - // DependencyManager::destroy(); - quit(); } From bd3d7124e299280ef5e2993e7131672873994f67 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 20 Feb 2015 13:31:58 -0800 Subject: [PATCH 36/56] cleanups --- assignment-client/src/AssignmentClient.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index f0461663a7..b9f6afa5d3 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -57,7 +57,6 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : DependencyManager::registerInheritance(); auto addressManager = DependencyManager::set(); auto nodeList = DependencyManager::set(NodeType::Unassigned); - // auto avatarHashMap = DependencyManager::set(); // make up a uuid for this child so the parent can tell us apart. This id will be changed // when the domain server hands over an assignment. @@ -141,8 +140,8 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : // Create Singleton objects on main thread NetworkAccessManager::getInstance(); - // DependencyManager::get(); + // Hook up a timer to send this child's status to the Monitor once per second setUpStatsToMonitor(); } From 907be67135719e4e6ba01c4f10487db8a083e71f Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 20 Feb 2015 13:34:51 -0800 Subject: [PATCH 37/56] cleanups --- assignment-client/src/AssignmentClient.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index b9f6afa5d3..465078099f 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -193,7 +193,7 @@ void AssignmentClient::sendAssignmentRequest() { localAssignmentServerPort)) { if (localAssignmentServerPort != _assignmentServerSocket.getPort()) { qDebug() << "Port for local assignment server read from shared memory is" - << localAssignmentServerPort; + << localAssignmentServerPort; _assignmentServerSocket.setPort(localAssignmentServerPort); nodeList->setAssignmentServerSocket(_assignmentServerSocket); @@ -203,7 +203,7 @@ void AssignmentClient::sendAssignmentRequest() { qDebug () << "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort(); } } - + nodeList->sendAssignment(_requestAssignment); } } From 4bba4fc387ab9c83547d65a4fd2531d3a2334607 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 20 Feb 2015 13:44:37 -0800 Subject: [PATCH 38/56] cleanups --- assignment-client/src/AssignmentClient.cpp | 2 +- assignment-client/src/AssignmentClientMonitor.cpp | 15 +++++---------- assignment-client/src/AssignmentClientMonitor.h | 3 --- domain-server/src/DomainServer.cpp | 2 +- libraries/networking/src/LimitedNodeList.h | 3 +-- 5 files changed, 8 insertions(+), 17 deletions(-) diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 465078099f..cf4b305bb0 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -203,7 +203,7 @@ void AssignmentClient::sendAssignmentRequest() { qDebug () << "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort(); } } - + nodeList->sendAssignment(_requestAssignment); } } diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 94975b0a4d..32830e2bb3 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -13,10 +13,7 @@ #include #include - - -#include // XXX need this? - +#include #include "AssignmentClientMonitor.h" #include "PacketHeaders.h" @@ -52,7 +49,6 @@ AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, const u // create a NodeList so we can receive stats from children DependencyManager::registerInheritance(); auto addressManager = DependencyManager::set(); - // auto nodeList = DependencyManager::set(NodeType::Unassigned); auto nodeList = DependencyManager::set(DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT, DEFAULT_ASSIGNMENT_CLIENT_MONITOR_DTLS_PORT); @@ -89,7 +85,7 @@ void AssignmentClientMonitor::spawnChildClient() { // make sure that the output from the child process appears in our output assignmentClient->setProcessChannelMode(QProcess::ForwardedChannels); - + assignmentClient->start(applicationFilePath(), _childArguments); qDebug() << "Spawned a child client with PID" << assignmentClient->pid(); } @@ -102,8 +98,6 @@ void AssignmentClientMonitor::checkSpares() { nodeList->removeSilentNodes(); - qDebug() << "check spares:"; - nodeList->eachNode([&](const SharedNodePointer& node){ AssignmentClientChildData *childData = static_cast(node->getLinkedData()); qDebug() << " " << node->getUUID() << childData->getChildType(); @@ -113,10 +107,11 @@ void AssignmentClientMonitor::checkSpares() { } }); - qDebug() << " spare count is" << spareCount; + if (spareCount != 1) { + qDebug() << " spare count is" << spareCount; + } if (spareCount < 1) { - qDebug() << "FORK"; spawnChildClient(); } diff --git a/assignment-client/src/AssignmentClientMonitor.h b/assignment-client/src/AssignmentClientMonitor.h index a91dfa93cc..8055b5d81f 100644 --- a/assignment-client/src/AssignmentClientMonitor.h +++ b/assignment-client/src/AssignmentClientMonitor.h @@ -45,14 +45,11 @@ public: void stopChildProcesses(); private slots: - // void childProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); void readPendingDatagrams(); void checkSpares(); private: void spawnChildClient(); - // QList > _childProcesses; - QStringList _childArguments; QTimer _checkSparesTimer; // every few seconds see if it need fewer or more spare children }; diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 30d6dd4348..64e0d335b1 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -244,7 +244,7 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) { populateStaticScriptedAssignmentsFromSettings(); auto nodeList = DependencyManager::set(domainServerPort, domainServerDTLSPort); - + // no matter the local port, save it to shared mem so that local assignment clients can ask what it is nodeList->putLocalPortIntoSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this); diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index e7ccbe7746..b53287562b 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -25,9 +25,8 @@ #include #include #include -#include - #include +#include #include From 70c96e496fdec6bb936102165bbcee80f3e177aa Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 20 Feb 2015 14:25:13 -0800 Subject: [PATCH 39/56] don't print ^a to qDebug for unassigned node type --- libraries/networking/src/Node.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/networking/src/Node.cpp b/libraries/networking/src/Node.cpp index 2bf792c6ee..2a38799707 100644 --- a/libraries/networking/src/Node.cpp +++ b/libraries/networking/src/Node.cpp @@ -149,7 +149,12 @@ QDataStream& operator>>(QDataStream& in, Node& node) { } QDebug operator<<(QDebug debug, const Node &node) { - debug.nospace() << NodeType::getNodeTypeName(node.getType()) << " (" << node.getType() << ")"; + debug.nospace() << NodeType::getNodeTypeName(node.getType()); + if (node.getType() == NodeType::Unassigned) { + debug.nospace() << " (1)"; + } else { + debug.nospace() << " (" << node.getType() << ")"; + } debug << " " << node.getUUID().toString().toLocal8Bit().constData() << " "; debug.nospace() << node.getPublicSocket() << "/" << node.getLocalSocket(); return debug.nospace(); From 8cee88acb495c3a775276ee579e80a4d616af48b Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 20 Feb 2015 14:25:43 -0800 Subject: [PATCH 40/56] network chatter between Monitor and AssignmentClients is expected to be localhost only --- assignment-client/src/AssignmentClient.cpp | 9 ++++-- .../src/AssignmentClientMonitor.cpp | 28 +++++++++++-------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index cf4b305bb0..5fcc380962 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -259,8 +259,13 @@ void AssignmentClient::readPendingDatagrams() { qDebug() << "Received an assignment that could not be unpacked. Re-requesting."; } } else if (packetTypeForPacket(receivedPacket) == PacketTypeStopNode) { - qDebug() << "Network told me to exit."; - emit stopAssignmentClient(); + if (senderSockAddr.getAddress() == QHostAddress::LocalHost || + senderSockAddr.getAddress() == QHostAddress::LocalHostIPv6) { + qDebug() << "Network told me to exit."; + emit stopAssignmentClient(); + } else { + qDebug() << "Got a stop packet from other than localhost."; + } } else { // have the NodeList attempt to handle it nodeList->processNodeData(senderSockAddr, receivedPacket); diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 32830e2bb3..d601990759 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -87,10 +87,12 @@ void AssignmentClientMonitor::spawnChildClient() { assignmentClient->setProcessChannelMode(QProcess::ForwardedChannels); assignmentClient->start(applicationFilePath(), _childArguments); + qDebug() << "Spawned a child client with PID" << assignmentClient->pid(); } + void AssignmentClientMonitor::checkSpares() { auto nodeList = DependencyManager::get(); QUuid aSpareId = ""; @@ -100,7 +102,6 @@ void AssignmentClientMonitor::checkSpares() { nodeList->eachNode([&](const SharedNodePointer& node){ AssignmentClientChildData *childData = static_cast(node->getLinkedData()); - qDebug() << " " << node->getUUID() << childData->getChildType(); if (childData->getChildType() == "none") { spareCount ++; aSpareId = node->getUUID(); @@ -142,17 +143,20 @@ void AssignmentClientMonitor::readPendingDatagrams() { QUuid packetUUID = uuidFromPacketHeader(receivedPacket); SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(receivedPacket); if (!matchingNode) { - // XXX only do this if from local machine - if (!packetUUID.isNull()) { - matchingNode = DependencyManager::get()->addOrUpdateNode - (packetUUID, NodeType::Unassigned, senderSockAddr, senderSockAddr, false); - AssignmentClientChildData *childData = new AssignmentClientChildData("unknown"); - matchingNode->setLinkedData(childData); - } else { - // tell unknown assignment-client child to exit. - qDebug() << "asking unknown child to exit."; - QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); - nodeList->writeUnverifiedDatagram(diePacket, senderSockAddr); + // The parent only expects to be talking with prorams running on this same machine. + if (senderSockAddr.getAddress() == QHostAddress::LocalHost || + senderSockAddr.getAddress() == QHostAddress::LocalHostIPv6) { + if (!packetUUID.isNull()) { + matchingNode = DependencyManager::get()->addOrUpdateNode + (packetUUID, NodeType::Unassigned, senderSockAddr, senderSockAddr, false); + AssignmentClientChildData *childData = new AssignmentClientChildData("unknown"); + matchingNode->setLinkedData(childData); + } else { + // tell unknown assignment-client child to exit. + qDebug() << "asking unknown child to exit."; + QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); + nodeList->writeUnverifiedDatagram(diePacket, senderSockAddr); + } } } From 270d509a1284c3b8fb3ca07e6ea077e9c7f49eb1 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 20 Feb 2015 14:29:12 -0800 Subject: [PATCH 41/56] cleanups --- assignment-client/src/AssignmentClientMonitor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index d601990759..2bddab9656 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -62,7 +62,7 @@ AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, const u } connect(&_checkSparesTimer, SIGNAL(timeout()), SLOT(checkSpares())); - _checkSparesTimer.start(5000); + _checkSparesTimer.start(NODE_SILENCE_THRESHOLD_MSECS * 3); } AssignmentClientMonitor::~AssignmentClientMonitor() { @@ -109,7 +109,7 @@ void AssignmentClientMonitor::checkSpares() { }); if (spareCount != 1) { - qDebug() << " spare count is" << spareCount; + qDebug() << "spare count is" << spareCount; } if (spareCount < 1) { From 27e6f99debfed792ef0ad4a5fb95e51f3a0e070f Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 20 Feb 2015 16:54:58 -0800 Subject: [PATCH 42/56] use strings for shapeType for JS Entity properties --- examples/html/entityProperties.html | 8 ++-- .../entities/src/EntityItemProperties.cpp | 44 +++++++++++++++++-- libraries/entities/src/EntityItemProperties.h | 3 ++ .../entities/src/EntityItemPropertiesMacros.h | 9 ---- 4 files changed, 47 insertions(+), 17 deletions(-) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index 84a8d23a74..ad2b359e79 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -406,7 +406,7 @@ elModelAnimationFrame.addEventListener('change', createEmitNumberPropertyUpdateFunction('animationFrameIndex')); elModelAnimationSettings.addEventListener('change', createEmitTextPropertyUpdateFunction('animationSettings')); elModelTextures.addEventListener('change', createEmitTextPropertyUpdateFunction('textures')); - elModelShapeType.addEventListener('change', createEmitNumberPropertyUpdateFunction('shapeType')); + elModelShapeType.addEventListener('change', createEmitTextPropertyUpdateFunction('shapeType')); elTextText.addEventListener('change', createEmitTextPropertyUpdateFunction('text')); elTextLineHeight.addEventListener('change', createEmitNumberPropertyUpdateFunction('lineHeight')); @@ -671,9 +671,9 @@
Shape Type
diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 353aab0a64..7f37799bbc 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -10,6 +10,7 @@ // #include +#include #include #include @@ -170,6 +171,35 @@ void EntityItemProperties::setLastEdited(quint64 usecTime) { _lastEdited = usecTime > _created ? usecTime : _created; } +const char* shapeTypeNames[] = {"none", "box", "sphere"}; + +QString EntityItemProperties::getShapeTypeString() const { + return QString(shapeTypeNames[_shapeType]); +} + +QHash stringToShapeTypeLookup; + +void buildStringToShapeTypeLookup() { + stringToShapeTypeLookup["none"] = SHAPE_TYPE_NONE; + stringToShapeTypeLookup["box"] = SHAPE_TYPE_BOX; + stringToShapeTypeLookup["sphere"] = SHAPE_TYPE_SPHERE; +} + +void EntityItemProperties::setShapeTypeFromString(const QString& shapeName) { + if (stringToShapeTypeLookup.empty()) { + buildStringToShapeTypeLookup(); + } + auto shapeTypeItr = stringToShapeTypeLookup.find(shapeName.toLower()); + ShapeType newShapeType = SHAPE_TYPE_NONE; + if (shapeTypeItr != stringToShapeTypeLookup.end()) { + newShapeType = shapeTypeItr.value(); + } + if (newShapeType != _shapeType) { + _shapeType = newShapeType; + _shapeTypeChanged = true; + } +} + EntityPropertyFlags EntityItemProperties::getChangedProperties() const { EntityPropertyFlags changedProperties; @@ -270,7 +300,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons COPY_PROPERTY_TO_QSCRIPTVALUE(lineHeight); COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(textColor, getTextColor()); COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(backgroundColor, getBackgroundColor()); - COPY_PROPERTY_TO_QSCRIPTVALUE(shapeType); + properties.setProperty("shapeType", getShapeTypeString()); // Sitting properties support QScriptValue sittingPoints = engine->newObject(); @@ -303,8 +333,6 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons } void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) { - - QScriptValue typeScriptValue = object.property("type"); if (typeScriptValue.isValid()) { setType(typeScriptValue.toVariant().toString()); @@ -350,7 +378,15 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) { COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(lineHeight, setLineHeight); COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(textColor, setTextColor); COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(backgroundColor, setBackgroundColor); - COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(shapeType, setShapeType, ShapeType); + + QScriptValue shapeType = object.property("shapeType"); + if (shapeType.isValid()) { + QString newValue = shapeType.toVariant().toString(); + if (_defaultSettings || newValue != getShapeTypeString()) { + setShapeTypeFromString(newValue); + } + } + _lastEdited = usecTimestampNow(); } diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 51779d3f56..070b80f754 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -183,6 +183,9 @@ public: DEFINE_PROPERTY_REF(PROP_BACKGROUND_COLOR, BackgroundColor, backgroundColor, xColor); DEFINE_PROPERTY_REF(PROP_SHAPE_TYPE, ShapeType, shapeType, ShapeType); + QString getShapeTypeString() const; + void setShapeTypeFromString(const QString& shapeName); + public: float getMaxDimension() const { return glm::max(_dimensions.x, _dimensions.y, _dimensions.z); } diff --git a/libraries/entities/src/EntityItemPropertiesMacros.h b/libraries/entities/src/EntityItemPropertiesMacros.h index 592f808e1a..9cf16c7a05 100644 --- a/libraries/entities/src/EntityItemPropertiesMacros.h +++ b/libraries/entities/src/EntityItemPropertiesMacros.h @@ -180,15 +180,6 @@ #define COPY_PROPERTY_TO_QSCRIPTVALUE(P) \ properties.setProperty(#P, _##P); -#define COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(P, S, E) \ - QScriptValue P = object.property(#P); \ - if (P.isValid()) { \ - E newValue = (E)(P.toVariant().toInt()); \ - if (_defaultSettings || newValue != _##P) { \ - S(newValue); \ - } \ - } - #define COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(P, S) \ QScriptValue P = object.property(#P); \ if (P.isValid()) { \ From 8d9685ee394f37e5d7d8a67ef04a3e9789a7a00c Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 21 Feb 2015 11:01:07 -0800 Subject: [PATCH 43/56] Fix Face Tracking menu operation --- interface/src/Menu.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index bd609a6840..c45fc6ed33 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -369,8 +369,8 @@ Menu::Menu() { faceTrackerGroup->addAction(noFaceTracker); #ifdef HAVE_FACESHIFT - QAction* faceshiftFaceTracker = addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::Faceshift, - 0, true, + QAction* faceshiftFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::Faceshift, + 0, false, qApp, SLOT(setActiveFaceTracker())); faceTrackerGroup->addAction(faceshiftFaceTracker); #endif @@ -381,7 +381,7 @@ Menu::Menu() { faceTrackerGroup->addAction(ddeFaceTracker); #ifdef HAVE_VISAGE - QAction* visageFaceTracker = addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::Visage, + QAction* visageFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::Visage, 0, false, qApp, SLOT(setActiveFaceTracker())); faceTrackerGroup->addAction(visageFaceTracker); From f169ab1238a7547636a6c9508afb40c42da03beb Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 21 Feb 2015 11:26:48 -0800 Subject: [PATCH 44/56] Tidy and document DDE face tracker UDP socket opening and closing --- interface/src/devices/DdeFaceTracker.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index c4797c4018..87a180bd1e 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -93,13 +93,10 @@ void DdeFaceTracker::update() { } void DdeFaceTracker::setEnabled(bool enabled) { + // isOpen() does not work as one might expect on QUdpSocket; don't test isOpen() before closing socket. + _udpSocket.close(); if (enabled) { - if (_udpSocket.isOpen()) { - _udpSocket.close(); - } _udpSocket.bind(_host, _port); - } else { - _udpSocket.close(); } } From 0fc4c732f7c339e7fe06bfa5e34ee1504f69c3b3 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 23 Feb 2015 10:13:47 -0800 Subject: [PATCH 45/56] use macro for copying shapeType string to script --- libraries/entities/src/EntityItemProperties.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 7f37799bbc..923eef667c 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -300,7 +300,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons COPY_PROPERTY_TO_QSCRIPTVALUE(lineHeight); COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(textColor, getTextColor()); COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(backgroundColor, getBackgroundColor()); - properties.setProperty("shapeType", getShapeTypeString()); + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(shapeType, getShapeTypeString()); // Sitting properties support QScriptValue sittingPoints = engine->newObject(); From 0b9b7f06cc8088b530b3b99d9d23d0f74322ed93 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 23 Feb 2015 11:12:19 -0800 Subject: [PATCH 46/56] address various comments from code review --- assignment-client/src/AssignmentClient.cpp | 8 ++--- assignment-client/src/AssignmentClientApp.cpp | 4 --- assignment-client/src/AssignmentClientApp.h | 1 - .../src/AssignmentClientChildData.cpp | 8 +++++ .../src/AssignmentClientChildData.h | 32 +++++++++++++++++ .../src/AssignmentClientMonitor.cpp | 34 ++++++++----------- .../src/AssignmentClientMonitor.h | 17 ++-------- libraries/networking/src/LimitedNodeList.cpp | 4 +-- libraries/networking/src/LimitedNodeList.h | 2 +- 9 files changed, 63 insertions(+), 47 deletions(-) create mode 100644 assignment-client/src/AssignmentClientChildData.cpp create mode 100644 assignment-client/src/AssignmentClientChildData.h diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 5fcc380962..2dfc3787de 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -159,8 +159,8 @@ void AssignmentClient::setUpStatsToMonitor() { quint16 localMonitorServerPort = DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT; auto nodeList = DependencyManager::get(); - nodeList->getLocalPortFromSharedMemory(ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY, - _localACMPortSharedMem, localMonitorServerPort); + nodeList->getLocalServerPortFromSharedMemory(ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY, + _localACMPortSharedMem, localMonitorServerPort); _assignmentClientMonitorSocket = HifiSockAddr(DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME, localMonitorServerPort, true); // send a stats packet every 1 seconds @@ -189,8 +189,8 @@ void AssignmentClient::sendAssignmentRequest() { if (_assignmentServerHostname == "localhost") { // we want to check again for the local domain-server port in case the DS has restarted quint16 localAssignmentServerPort; - if (nodeList->getLocalPortFromSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, _localASPortSharedMem, - localAssignmentServerPort)) { + if (nodeList->getLocalServerPortFromSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, _localASPortSharedMem, + localAssignmentServerPort)) { if (localAssignmentServerPort != _assignmentServerSocket.getPort()) { qDebug() << "Port for local assignment server read from shared memory is" << localAssignmentServerPort; diff --git a/assignment-client/src/AssignmentClientApp.cpp b/assignment-client/src/AssignmentClientApp.cpp index 8848b59c49..477f1a2cf8 100644 --- a/assignment-client/src/AssignmentClientApp.cpp +++ b/assignment-client/src/AssignmentClientApp.cpp @@ -64,7 +64,3 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : client.exec(); } } - - -AssignmentClientApp::~AssignmentClientApp() { -} diff --git a/assignment-client/src/AssignmentClientApp.h b/assignment-client/src/AssignmentClientApp.h index 09952ad19c..c5099ff25c 100644 --- a/assignment-client/src/AssignmentClientApp.h +++ b/assignment-client/src/AssignmentClientApp.h @@ -15,5 +15,4 @@ class AssignmentClientApp : public QCoreApplication { Q_OBJECT public: AssignmentClientApp(int argc, char* argv[]); - ~AssignmentClientApp(); }; diff --git a/assignment-client/src/AssignmentClientChildData.cpp b/assignment-client/src/AssignmentClientChildData.cpp new file mode 100644 index 0000000000..de34613ec9 --- /dev/null +++ b/assignment-client/src/AssignmentClientChildData.cpp @@ -0,0 +1,8 @@ + +#include "AssignmentClientChildData.h" + + +AssignmentClientChildData::AssignmentClientChildData(QString childType) : + _childType(childType) +{ +} diff --git a/assignment-client/src/AssignmentClientChildData.h b/assignment-client/src/AssignmentClientChildData.h new file mode 100644 index 0000000000..6fd5f72f7f --- /dev/null +++ b/assignment-client/src/AssignmentClientChildData.h @@ -0,0 +1,32 @@ +// +// AssignmentClientChildData.h +// assignment-client/src +// +// Created by Seth Alves on 2/23/2015. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_AssignmentClientChildData_h +#define hifi_AssignmentClientChildData_h + +#include + + +class AssignmentClientChildData : public NodeData { + public: + AssignmentClientChildData(QString childType); + + QString getChildType() { return _childType; } + void setChildType(QString childType) { _childType = childType; } + + // implement parseData to return 0 so we can be a subclass of NodeData + int parseData(const QByteArray& packet) { return 0; } + + private: + QString _childType; +}; + +#endif // hifi_AssignmentClientChildData_h diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 2bddab9656..803c7fd5c7 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -16,6 +16,7 @@ #include #include "AssignmentClientMonitor.h" +#include "AssignmentClientChildData.h" #include "PacketHeaders.h" #include "SharedUtil.h" @@ -72,12 +73,12 @@ AssignmentClientMonitor::~AssignmentClientMonitor() { void AssignmentClientMonitor::stopChildProcesses() { auto nodeList = DependencyManager::get(); - nodeList->eachNode([&](const SharedNodePointer& node){ - qDebug() << "asking child" << node->getUUID() << "to exit."; - node->activateLocalSocket(); - QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); - nodeList->writeUnverifiedDatagram(diePacket, *node->getActiveSocket()); - }); + nodeList->eachNode([&](const SharedNodePointer& node) { + qDebug() << "asking child" << node->getUUID() << "to exit."; + node->activateLocalSocket(); + QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); + nodeList->writeUnverifiedDatagram(diePacket, *node->getActiveSocket()); + }); } void AssignmentClientMonitor::spawnChildClient() { @@ -100,13 +101,13 @@ void AssignmentClientMonitor::checkSpares() { nodeList->removeSilentNodes(); - nodeList->eachNode([&](const SharedNodePointer& node){ - AssignmentClientChildData *childData = static_cast(node->getLinkedData()); - if (childData->getChildType() == "none") { - spareCount ++; - aSpareId = node->getUUID(); - } - }); + nodeList->eachNode([&](const SharedNodePointer& node) { + AssignmentClientChildData *childData = static_cast(node->getLinkedData()); + if (childData->getChildType() == "none") { + spareCount ++; + aSpareId = node->getUUID(); + } + }); if (spareCount != 1) { qDebug() << "spare count is" << spareCount; @@ -189,10 +190,3 @@ void AssignmentClientMonitor::readPendingDatagrams() { } -AssignmentClientChildData::AssignmentClientChildData(QString childType) { - _childType = childType; -} - - -AssignmentClientChildData::~AssignmentClientChildData() { -} diff --git a/assignment-client/src/AssignmentClientMonitor.h b/assignment-client/src/AssignmentClientMonitor.h index 8055b5d81f..71ae34bc8c 100644 --- a/assignment-client/src/AssignmentClientMonitor.h +++ b/assignment-client/src/AssignmentClientMonitor.h @@ -19,23 +19,10 @@ #include +#include "AssignmentClientChildData.h" + extern const char* NUM_FORKS_PARAMETER; -class AssignmentClientChildData : public NodeData { - public: - AssignmentClientChildData(QString childType); - ~AssignmentClientChildData(); - - QString getChildType() { return _childType; } - void setChildType(QString childType) { _childType = childType; } - - // implement parseData to return 0 so we can be a subclass of NodeData - int parseData(const QByteArray& packet) { return 0; } - - private: - QString _childType; -}; - class AssignmentClientMonitor : public QCoreApplication { Q_OBJECT diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 075fd5a44b..4fc0648c4d 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -688,8 +688,8 @@ void LimitedNodeList::putLocalPortIntoSharedMemory(const QString key, QObject* p } -bool LimitedNodeList::getLocalPortFromSharedMemory(const QString key, QSharedMemory* &sharedMem, - quint16& localPort) { +bool LimitedNodeList::getLocalServerPortFromSharedMemory(const QString key, QSharedMemory* &sharedMem, + quint16& localPort) { if (!sharedMem) { sharedMem = new QSharedMemory(key, this); diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index b53287562b..27cddb4b24 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -176,7 +176,7 @@ public: } void putLocalPortIntoSharedMemory(const QString key, QObject* parent); - bool getLocalPortFromSharedMemory(const QString key, QSharedMemory* &sharedMem, quint16& localPort); + bool getLocalServerPortFromSharedMemory(const QString key, QSharedMemory* &sharedMem, quint16& localPort); public slots: void reset(); From 2e1c1229152735f3b77a8e16b7c8324cd1d54579 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 23 Feb 2015 11:38:56 -0800 Subject: [PATCH 47/56] moved ShapeType boilerplate stuff macos --- .../entities/src/EntityItemProperties.cpp | 20 ++++++------------- libraries/entities/src/EntityItemProperties.h | 5 +---- .../entities/src/EntityItemPropertiesMacros.h | 20 +++++++++++++++++++ 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 923eef667c..8a809dee72 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -173,10 +173,6 @@ void EntityItemProperties::setLastEdited(quint64 usecTime) { const char* shapeTypeNames[] = {"none", "box", "sphere"}; -QString EntityItemProperties::getShapeTypeString() const { - return QString(shapeTypeNames[_shapeType]); -} - QHash stringToShapeTypeLookup; void buildStringToShapeTypeLookup() { @@ -185,6 +181,10 @@ void buildStringToShapeTypeLookup() { stringToShapeTypeLookup["sphere"] = SHAPE_TYPE_SPHERE; } +QString EntityItemProperties::getShapeTypeAsString() const { + return QString(shapeTypeNames[_shapeType]); +} + void EntityItemProperties::setShapeTypeFromString(const QString& shapeName) { if (stringToShapeTypeLookup.empty()) { buildStringToShapeTypeLookup(); @@ -300,7 +300,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons COPY_PROPERTY_TO_QSCRIPTVALUE(lineHeight); COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(textColor, getTextColor()); COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(backgroundColor, getBackgroundColor()); - COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(shapeType, getShapeTypeString()); + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(shapeType, getShapeTypeAsString()); // Sitting properties support QScriptValue sittingPoints = engine->newObject(); @@ -378,15 +378,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) { COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(lineHeight, setLineHeight); COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(textColor, setTextColor); COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(backgroundColor, setBackgroundColor); - - QScriptValue shapeType = object.property("shapeType"); - if (shapeType.isValid()) { - QString newValue = shapeType.toVariant().toString(); - if (_defaultSettings || newValue != getShapeTypeString()) { - setShapeTypeFromString(newValue); - } - } - + COPY_PROPERTY_FROM_QSCRITPTVALUE_ENUM(shapeType, ShapeType); _lastEdited = usecTimestampNow(); } diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 070b80f754..2391bcde84 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -181,10 +181,7 @@ public: DEFINE_PROPERTY(PROP_LINE_HEIGHT, LineHeight, lineHeight, float); DEFINE_PROPERTY_REF(PROP_TEXT_COLOR, TextColor, textColor, xColor); DEFINE_PROPERTY_REF(PROP_BACKGROUND_COLOR, BackgroundColor, backgroundColor, xColor); - DEFINE_PROPERTY_REF(PROP_SHAPE_TYPE, ShapeType, shapeType, ShapeType); - - QString getShapeTypeString() const; - void setShapeTypeFromString(const QString& shapeName); + DEFINE_PROPERTY_REF_ENUM(PROP_SHAPE_TYPE, ShapeType, shapeType, ShapeType); public: float getMaxDimension() const { return glm::max(_dimensions.x, _dimensions.y, _dimensions.z); } diff --git a/libraries/entities/src/EntityItemPropertiesMacros.h b/libraries/entities/src/EntityItemPropertiesMacros.h index 9cf16c7a05..5e04614656 100644 --- a/libraries/entities/src/EntityItemPropertiesMacros.h +++ b/libraries/entities/src/EntityItemPropertiesMacros.h @@ -271,6 +271,15 @@ } \ } \ } + +#define COPY_PROPERTY_FROM_QSCRITPTVALUE_ENUM(P, S) \ + QScriptValue P = object.property(#P); \ + if (P.isValid()) { \ + QString newValue = P.toVariant().toString(); \ + if (_defaultSettings || newValue != get##S##AsString()) { \ + set##S##FromString(newValue); \ + } \ + } #define CONSTRUCT_PROPERTY(n, V) \ _##n(V), \ @@ -312,6 +321,17 @@ T _##n; \ bool _##n##Changed; +#define DEFINE_PROPERTY_REF_ENUM(P, N, n, T) \ + public: \ + const T& get##N() const { return _##n; } \ + void set##N(const T& value) { _##n = value; _##n##Changed = true; } \ + bool n##Changed() const { return _##n##Changed; } \ + QString get##N##AsString() const; \ + void set##N##FromString(const QString& name); \ + private: \ + T _##n; \ + bool _##n##Changed; + #define DEBUG_PROPERTY_IF_CHANGED(D, P, N, n, x) \ if (P.n##Changed()) { \ D << " " << #n << ":" << P.get##N() << x << "\n"; \ From f2fc7815232a7ebbc2dcd6241a357cf661fb64fe Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 23 Feb 2015 11:42:36 -0800 Subject: [PATCH 48/56] change shapeType to use strings in billiards.js --- examples/example/games/billiards.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/example/games/billiards.js b/examples/example/games/billiards.js index cb30cc631f..d4bc71ba37 100644 --- a/examples/example/games/billiards.js +++ b/examples/example/games/billiards.js @@ -122,7 +122,7 @@ function makeBalls(pos) { gravity: { x: 0, y: GRAVITY, z: 0 }, ignoreCollisions: false, damping: 0.50, - shapeType: 2, + shapeType: "sphere", collisionsWillMove: true })); ballPosition.z += (BALL_SIZE + BALL_GAP) * SCALE; ballNumber++; @@ -143,7 +143,7 @@ function makeBalls(pos) { velocity: {x: 0, y: 0, z: 0 }, ignoreCollisions: false, damping: 0.50, - shapeType: 2, + shapeType: "sphere", collisionsWillMove: true }); } From 3cd0a70641da47813a643b7cd29d78b54826b60f Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 23 Feb 2015 14:35:44 -0800 Subject: [PATCH 49/56] store shapeType whenever it is explicitly changed --- libraries/entities/src/EntityItemProperties.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 8a809dee72..f3f84876ba 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -190,12 +190,8 @@ void EntityItemProperties::setShapeTypeFromString(const QString& shapeName) { buildStringToShapeTypeLookup(); } auto shapeTypeItr = stringToShapeTypeLookup.find(shapeName.toLower()); - ShapeType newShapeType = SHAPE_TYPE_NONE; if (shapeTypeItr != stringToShapeTypeLookup.end()) { - newShapeType = shapeTypeItr.value(); - } - if (newShapeType != _shapeType) { - _shapeType = newShapeType; + _shapeType = shapeTypeItr.value(); _shapeTypeChanged = true; } } From f5a7a19bc3f239e04836f98d7c8fc0d24cfe78de Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 24 Feb 2015 10:41:20 -0800 Subject: [PATCH 50/56] coding convention --- libraries/networking/src/LimitedNodeList.cpp | 2 +- libraries/networking/src/LimitedNodeList.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 4fc0648c4d..b240f0df9e 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -688,7 +688,7 @@ void LimitedNodeList::putLocalPortIntoSharedMemory(const QString key, QObject* p } -bool LimitedNodeList::getLocalServerPortFromSharedMemory(const QString key, QSharedMemory* &sharedMem, +bool LimitedNodeList::getLocalServerPortFromSharedMemory(const QString key, QSharedMemory*& sharedMem, quint16& localPort) { if (!sharedMem) { sharedMem = new QSharedMemory(key, this); diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 27cddb4b24..02234ee4f7 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -176,7 +176,7 @@ public: } void putLocalPortIntoSharedMemory(const QString key, QObject* parent); - bool getLocalServerPortFromSharedMemory(const QString key, QSharedMemory* &sharedMem, quint16& localPort); + bool getLocalServerPortFromSharedMemory(const QString key, QSharedMemory*& sharedMem, quint16& localPort); public slots: void reset(); From 5f9af610c268eab27c303a229743d48b974a1306 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 24 Feb 2015 10:41:58 -0800 Subject: [PATCH 51/56] coding convention --- libraries/networking/src/LimitedNodeList.cpp | 2 +- libraries/networking/src/LimitedNodeList.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 4fc0648c4d..b240f0df9e 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -688,7 +688,7 @@ void LimitedNodeList::putLocalPortIntoSharedMemory(const QString key, QObject* p } -bool LimitedNodeList::getLocalServerPortFromSharedMemory(const QString key, QSharedMemory* &sharedMem, +bool LimitedNodeList::getLocalServerPortFromSharedMemory(const QString key, QSharedMemory*& sharedMem, quint16& localPort) { if (!sharedMem) { sharedMem = new QSharedMemory(key, this); diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 27cddb4b24..02234ee4f7 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -176,7 +176,7 @@ public: } void putLocalPortIntoSharedMemory(const QString key, QObject* parent); - bool getLocalServerPortFromSharedMemory(const QString key, QSharedMemory* &sharedMem, quint16& localPort); + bool getLocalServerPortFromSharedMemory(const QString key, QSharedMemory*& sharedMem, quint16& localPort); public slots: void reset(); From d74856e01b50737a44d900299974187b901ab925 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 24 Feb 2015 11:21:04 -0800 Subject: [PATCH 52/56] add angularVelocity to controller --- interface/src/devices/SixenseManager.cpp | 12 ++++++++++++ .../scripting/ControllerScriptingInterface.cpp | 15 +++++++++++++++ .../src/scripting/ControllerScriptingInterface.h | 1 + libraries/avatars/src/HandData.cpp | 2 +- libraries/avatars/src/HandData.h | 4 +++- 5 files changed, 32 insertions(+), 2 deletions(-) diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index ffaa5260db..609ac7b349 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -260,6 +260,18 @@ void SixenseManager::update(float deltaTime) { float sign = (i == 0) ? -1.0f : 1.0f; rotation *= glm::angleAxis(sign * PI/4.0f, glm::vec3(0.0f, 0.0f, 1.0f)); + // Angular Velocity of Palm + glm::quat deltaRotation = rotation * glm::inverse(palm->getRawRotation()); + glm::vec3 angularVelocity(0.0f); + float rotationAngle = glm::angle(deltaRotation); + if ((rotationAngle > EPSILON) && (deltaTime > 0.0f)) { + angularVelocity = glm::normalize(glm::axis(deltaRotation)); + angularVelocity *= (rotationAngle / deltaTime); + palm->setRawAngularVelocity(angularVelocity); + } else { + palm->setRawAngularVelocity(glm::vec3(0.0f)); + } + if (_lowVelocityFilter) { // Use a velocity sensitive filter to damp small motions and preserve large ones with // no latency. diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index 929a763e70..2188f45374 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -208,6 +208,21 @@ glm::quat ControllerScriptingInterface::getSpatialControlRawRotation(int control } return glm::quat(); // bad index } + +glm::vec3 ControllerScriptingInterface::getSpatialControlRawAngularVelocity(int controlIndex) const { + int palmIndex = controlIndex / NUMBER_OF_SPATIALCONTROLS_PER_PALM; + int controlOfPalm = controlIndex % NUMBER_OF_SPATIALCONTROLS_PER_PALM; + const PalmData* palmData = getActivePalm(palmIndex); + if (palmData) { + switch (controlOfPalm) { + case PALM_SPATIALCONTROL: + return palmData->getRawAngularVelocity(); + case TIP_SPATIALCONTROL: + return palmData->getRawAngularVelocity(); // Tip = palm angular velocity + } + } + return glm::vec3(0); // bad index +} glm::vec3 ControllerScriptingInterface::getSpatialControlNormal(int controlIndex) const { int palmIndex = controlIndex / NUMBER_OF_SPATIALCONTROLS_PER_PALM; diff --git a/interface/src/scripting/ControllerScriptingInterface.h b/interface/src/scripting/ControllerScriptingInterface.h index d56d159c06..c088dd6c9a 100644 --- a/interface/src/scripting/ControllerScriptingInterface.h +++ b/interface/src/scripting/ControllerScriptingInterface.h @@ -96,6 +96,7 @@ public slots: virtual glm::vec3 getSpatialControlVelocity(int controlIndex) const; virtual glm::vec3 getSpatialControlNormal(int controlIndex) const; virtual glm::quat getSpatialControlRawRotation(int controlIndex) const; + virtual glm::vec3 getSpatialControlRawAngularVelocity(int controlIndex) const; virtual void captureKeyEvents(const KeyEvent& event); virtual void releaseKeyEvents(const KeyEvent& event); diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index 5d850d06d0..9a9b51c1c8 100644 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -67,7 +67,7 @@ PalmData::PalmData(HandData* owningHandData) : _rawRotation(0.0f, 0.0f, 0.0f, 1.0f), _rawPosition(0.0f), _rawVelocity(0.0f), -_rotationalVelocity(0.0f), +_rawAngularVelocity(0.0f), _totalPenetration(0.0f), _controllerButtons(0), _isActive(false), diff --git a/libraries/avatars/src/HandData.h b/libraries/avatars/src/HandData.h index 534ea67726..a5e2b2907e 100644 --- a/libraries/avatars/src/HandData.h +++ b/libraries/avatars/src/HandData.h @@ -98,6 +98,8 @@ public: void setRawPosition(const glm::vec3& pos) { _rawPosition = pos; } void setRawVelocity(const glm::vec3& velocity) { _rawVelocity = velocity; } const glm::vec3& getRawVelocity() const { return _rawVelocity; } + void setRawAngularVelocity(const glm::vec3& angularVelocity) { _rawAngularVelocity = angularVelocity; } + const glm::vec3& getRawAngularVelocity() const { return _rawAngularVelocity; } void addToPosition(const glm::vec3& delta); void addToPenetration(const glm::vec3& penetration) { _totalPenetration += penetration; } @@ -148,7 +150,7 @@ private: glm::quat _rawRotation; glm::vec3 _rawPosition; glm::vec3 _rawVelocity; - glm::vec3 _rotationalVelocity; + glm::vec3 _rawAngularVelocity; glm::quat _lastRotation; glm::vec3 _tipPosition; From 7489b468f3a4f473ed6825ac5c81d12242330c01 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 24 Feb 2015 11:48:35 -0800 Subject: [PATCH 53/56] give angular velocity to the thrown ball --- examples/controllers/hydra/toyball.js | 72 +++++++++++++++++++-------- 1 file changed, 52 insertions(+), 20 deletions(-) diff --git a/examples/controllers/hydra/toyball.js b/examples/controllers/hydra/toyball.js index b2ce6c1463..06e7f5a2e7 100644 --- a/examples/controllers/hydra/toyball.js +++ b/examples/controllers/hydra/toyball.js @@ -29,15 +29,21 @@ var RIGHT_BUTTON_FWD = 11; var RIGHT_BUTTON_3 = 9; var BALL_RADIUS = 0.08; -var GRAVITY_STRENGTH = 1.0; +var GRAVITY_STRENGTH = 3.0; var HELD_COLOR = { red: 240, green: 0, blue: 0 }; var THROWN_COLOR = { red: 128, green: 0, blue: 0 }; +var averageLinearVelocity = [ { x: 0, y: 0, z : 0 }, { x: 0, y: 0, z : 0 } ]; + +var LIFETIME_SECONDS = 600; + +var BALL_MODEL_URL = "https://hifi-public.s3.amazonaws.com/ryan/baseball4.fbx"; + var leftBallAlreadyInHand = false; var rightBallAlreadyInHand = false; -var leftHandEntity; -var rightHandEntity; +var leftHandEntity = false; +var rightHandEntity = false; var newSound = SoundCache.getSound("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/throw.raw"); var catchSound = SoundCache.getSound("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/catch.raw"); @@ -67,31 +73,55 @@ function checkControllerSide(whichSide) { var BUTTON_3; var TRIGGER; var palmPosition; + var palmRotation; var ballAlreadyInHand; var handMessage; + var linearVelocity; + var angularVelocity; + var AVERAGE_FACTOR = 0.33; if (whichSide == LEFT_PALM) { BUTTON_FWD = LEFT_BUTTON_FWD; BUTTON_3 = LEFT_BUTTON_3; TRIGGER = 0; palmPosition = Controller.getSpatialControlPosition(LEFT_PALM); + palmRotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(LEFT_PALM)); ballAlreadyInHand = leftBallAlreadyInHand; handMessage = "LEFT"; + averageLinearVelocity[0] = Vec3.sum(Vec3.multiply(AVERAGE_FACTOR, Controller.getSpatialControlVelocity(LEFT_TIP)), + Vec3.multiply(1.0 - AVERAGE_FACTOR, averageLinearVelocity[0])); + linearVelocity = averageLinearVelocity[0]; + angularVelocity = Vec3.multiplyQbyV(MyAvatar.orientation, Controller.getSpatialControlRawAngularVelocity(LEFT_TIP)); + angularVelocity = Vec3.multiply(180.0 / Math.PI, angularVelocity); } else { BUTTON_FWD = RIGHT_BUTTON_FWD; BUTTON_3 = RIGHT_BUTTON_3; TRIGGER = 1; palmPosition = Controller.getSpatialControlPosition(RIGHT_PALM); + palmRotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(RIGHT_PALM)); ballAlreadyInHand = rightBallAlreadyInHand; + averageLinearVelocity[1] = Vec3.sum(Vec3.multiply(AVERAGE_FACTOR, Controller.getSpatialControlVelocity(RIGHT_TIP)), + Vec3.multiply(1.0 - AVERAGE_FACTOR, averageLinearVelocity[1])); + linearVelocity = averageLinearVelocity[1]; + angularVelocity = Vec3.multiplyQbyV(MyAvatar.orientation, Controller.getSpatialControlRawAngularVelocity(RIGHT_TIP)); + angularVelocity = Vec3.multiply(180.0 / Math.PI, angularVelocity); handMessage = "RIGHT"; } var grabButtonPressed = (Controller.isButtonPressed(BUTTON_FWD) || Controller.isButtonPressed(BUTTON_3) || (Controller.getTriggerValue(TRIGGER) > 0.5)); // If I don't currently have a ball in my hand, then try to catch closest one + if (leftHandEntity && !leftHandEntity.isKnownID) { + leftHandEntity = Entities.identifyEntity(leftHandEntity); + } + if (rightHandEntity && !rightHandEntity.isKnownID) { + rightHandEntity = Entities.identifyEntity(rightHandEntity); + } + if (!ballAlreadyInHand && grabButtonPressed) { var closestEntity = Entities.findClosestEntity(palmPosition, targetRadius); + //if (closestEntity.isKnownID && ((leftHandEntity && (closestEntity.id == leftHandEntity.id)) || (rightHandEntity && (closestEntity.id == rightHandEntity.id)))) { if (closestEntity.isKnownID) { debugPrint(handMessage + " HAND- CAUGHT SOMETHING!!"); @@ -107,13 +137,14 @@ function checkControllerSide(whichSide) { var properties = { position: { x: ballPosition.x, y: ballPosition.y, z: ballPosition.z }, - color: HELD_COLOR, + rotation: palmRotation, + color: HELD_COLOR, velocity : { x: 0, y: 0, z: 0}, - lifetime : 600, - inHand: true }; + gravity: { x: 0, y: 0, z: 0} + }; Entities.editEntity(closestEntity, properties); - Audio.playSound(catchSound, { position: ballPosition }); + Audio.playSound(catchSound, { position: ballPosition }); return; // exit early } @@ -129,18 +160,20 @@ function checkControllerSide(whichSide) { if (grabButtonPressed && !ballAlreadyInHand) { var ballPosition = getBallHoldPosition(whichSide); var properties = { - type: "Sphere", + type: "Model", + modelURL: BALL_MODEL_URL, position: { x: ballPosition.x, y: ballPosition.y, - z: ballPosition.z }, + z: ballPosition.z }, + rotation: palmRotation, velocity: { x: 0, y: 0, z: 0}, gravity: { x: 0, y: 0, z: 0}, - inHand: true, dimensions: { x: BALL_RADIUS * 2, y: BALL_RADIUS * 2, z: BALL_RADIUS * 2 }, damping: 0.00001, + shapeType: "sphere", + collisionsWillMove: false, color: HELD_COLOR, - - lifetime: 600 // 10 seconds - same as default, not needed but here as an example + lifetime: LIFETIME_SECONDS }; newEntity = Entities.addEntity(properties); @@ -174,21 +207,20 @@ function checkControllerSide(whichSide) { var properties = { position: { x: ballPosition.x, y: ballPosition.y, z: ballPosition.z }, + rotation: palmRotation, + velocity: { x: 0, y: 0, z: 0}, + gravity: { x: 0, y: 0, z: 0}, }; Entities.editEntity(handEntity, properties); } else { debugPrint(">>>>> " + handMessage + "-BALL IN HAND, not grabbing, THROW!!!"); // If toy ball just released, add velocity to it! - var tipVelocity = Controller.getSpatialControlVelocity(whichTip); - var THROWN_VELOCITY_SCALING = 1.5; var properties = { - velocity: { x: tipVelocity.x * THROWN_VELOCITY_SCALING, - y: tipVelocity.y * THROWN_VELOCITY_SCALING, - z: tipVelocity.z * THROWN_VELOCITY_SCALING } , + velocity: linearVelocity, + rotation: palmRotation, + angularVelocity: angularVelocity, collisionsWillMove: true, - inHand: false, color: THROWN_COLOR, - lifetime: 10, gravity: { x: 0, y: -GRAVITY_STRENGTH, z: 0}, }; @@ -216,7 +248,7 @@ function checkController(deltaTime) { // this is expected for hydras if (!(numberOfButtons==12 && numberOfTriggers == 2 && controllersPerTrigger == 2)) { - debugPrint("no hydra connected?"); + debugPrint("total buttons = " + numberOfButtons + ", Triggers = " + numberOfTriggers + ", controllers/trigger = " + controllersPerTrigger); return; // bail if no hydra } From 9d021a1a1ee166e65c71ec003791cbb1fca5b5b3 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 24 Feb 2015 11:49:12 -0800 Subject: [PATCH 54/56] remove unused line --- examples/controllers/hydra/toyball.js | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/controllers/hydra/toyball.js b/examples/controllers/hydra/toyball.js index 06e7f5a2e7..5306769e95 100644 --- a/examples/controllers/hydra/toyball.js +++ b/examples/controllers/hydra/toyball.js @@ -121,7 +121,6 @@ function checkControllerSide(whichSide) { if (!ballAlreadyInHand && grabButtonPressed) { var closestEntity = Entities.findClosestEntity(palmPosition, targetRadius); - //if (closestEntity.isKnownID && ((leftHandEntity && (closestEntity.id == leftHandEntity.id)) || (rightHandEntity && (closestEntity.id == rightHandEntity.id)))) { if (closestEntity.isKnownID) { debugPrint(handMessage + " HAND- CAUGHT SOMETHING!!"); From 573390b42960b394adb75cd16b6d48930288354c Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 24 Feb 2015 11:55:41 -0800 Subject: [PATCH 55/56] fix dice for collision shapes, add angular velocity --- examples/dice.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/dice.js b/examples/dice.js index d33da576c1..1205f38ee1 100644 --- a/examples/dice.js +++ b/examples/dice.js @@ -53,8 +53,10 @@ function shootDice(position, velocity) { position: position, velocity: velocity, rotation: Quat.fromPitchYawRollDegrees(Math.random() * 360, Math.random() * 360, Math.random() * 360), + angularVelocity: { x: Math.random() * 100, y: Math.random() * 100, z: Math.random() * 100 }, lifetime: LIFETIME, gravity: { x: 0, y: GRAVITY, z: 0 }, + shapeType: "box", collisionsWillMove: true })); position = Vec3.sum(position, Vec3.multiply(DIE_SIZE, Vec3.normalize(Quat.getRight(Camera.getOrientation())))); From 09ffcbb2e88f35a48ba7e46138cabbe4fa08e2c9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 24 Feb 2015 12:30:40 -0800 Subject: [PATCH 56/56] Revert "Merge pull request #4324 from sethalves/assignment-client-keep-a-spare" This reverts commit 087e2babde1329c242484e0e7f4ffbfa3e3206ea, reversing changes made to 5202d2136a0adfb2cf2558847b85a1f7ec94457d. --- assignment-client/src/AssignmentClient.cpp | 87 +++------- assignment-client/src/AssignmentClient.h | 11 +- assignment-client/src/AssignmentClientApp.cpp | 66 -------- assignment-client/src/AssignmentClientApp.h | 18 -- .../src/AssignmentClientChildData.cpp | 8 - .../src/AssignmentClientChildData.h | 32 ---- .../src/AssignmentClientMonitor.cpp | 158 ++++-------------- .../src/AssignmentClientMonitor.h | 13 +- assignment-client/src/main.cpp | 30 +++- domain-server/src/DomainServer.cpp | 14 +- libraries/networking/src/AddressManager.cpp | 4 +- libraries/networking/src/LimitedNodeList.cpp | 38 ----- libraries/networking/src/LimitedNodeList.h | 9 - libraries/networking/src/Node.cpp | 7 +- libraries/networking/src/NodeList.cpp | 8 +- libraries/networking/src/NodeList.h | 1 - libraries/networking/src/PacketHeaders.cpp | 3 - libraries/networking/src/PacketHeaders.h | 4 +- 18 files changed, 108 insertions(+), 403 deletions(-) delete mode 100644 assignment-client/src/AssignmentClientApp.cpp delete mode 100644 assignment-client/src/AssignmentClientApp.h delete mode 100644 assignment-client/src/AssignmentClientChildData.cpp delete mode 100644 assignment-client/src/AssignmentClientChildData.h diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 2dfc3787de..bf67d4d597 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -18,10 +18,10 @@ #include #include #include +#include #include #include #include -#include #include #include #include @@ -43,8 +43,7 @@ int hifiSockAddrMeta = qRegisterMetaType("HifiSockAddr"); AssignmentClient::AssignmentClient(int &argc, char **argv) : QCoreApplication(argc, argv), _assignmentServerHostname(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME), - _localASPortSharedMem(NULL), - _localACMPortSharedMem(NULL) + _localASPortSharedMem(NULL) { LogUtils::init(); @@ -57,11 +56,7 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : DependencyManager::registerInheritance(); auto addressManager = DependencyManager::set(); auto nodeList = DependencyManager::set(NodeType::Unassigned); - - // make up a uuid for this child so the parent can tell us apart. This id will be changed - // when the domain server hands over an assignment. - QUuid nodeUUID = QUuid::createUuid(); - nodeList->setSessionUUID(nodeUUID); + auto avatarHashMap = DependencyManager::set(); // setup a shutdown event listener to handle SIGTERM or WM_CLOSE for us #ifdef _WIN32 @@ -128,8 +123,9 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : // call a timer function every ASSIGNMENT_REQUEST_INTERVAL_MSECS to ask for assignment, if required qDebug() << "Waiting for assignment -" << _requestAssignment; - connect(&_requestTimer, SIGNAL(timeout()), SLOT(sendAssignmentRequest())); - _requestTimer.start(ASSIGNMENT_REQUEST_INTERVAL_MSECS); + QTimer* timer = new QTimer(this); + connect(timer, SIGNAL(timeout()), SLOT(sendAssignmentRequest())); + timer->start(ASSIGNMENT_REQUEST_INTERVAL_MSECS); // connect our readPendingDatagrams method to the readyRead() signal of the socket connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClient::readPendingDatagrams); @@ -140,45 +136,6 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : // Create Singleton objects on main thread NetworkAccessManager::getInstance(); - - // Hook up a timer to send this child's status to the Monitor once per second - setUpStatsToMonitor(); -} - - -void AssignmentClient::stopAssignmentClient() { - qDebug() << "Exiting."; - _requestTimer.stop(); - _statsTimerACM.stop(); - quit(); -} - - -void AssignmentClient::setUpStatsToMonitor() { - // Figure out the address to send out stats to - quint16 localMonitorServerPort = DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT; - auto nodeList = DependencyManager::get(); - - nodeList->getLocalServerPortFromSharedMemory(ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY, - _localACMPortSharedMem, localMonitorServerPort); - _assignmentClientMonitorSocket = HifiSockAddr(DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME, localMonitorServerPort, true); - - // send a stats packet every 1 seconds - connect(&_statsTimerACM, &QTimer::timeout, this, &AssignmentClient::sendStatsPacketToACM); - _statsTimerACM.start(1000); -} - -void AssignmentClient::sendStatsPacketToACM() { - // tell the assignment client monitor what this assignment client is doing (if anything) - QJsonObject statsObject; - auto nodeList = DependencyManager::get(); - - if (_currentAssignment) { - statsObject["assignment_type"] = _currentAssignment->getTypeName(); - } else { - statsObject["assignment_type"] = "none"; - } - nodeList->sendStats(statsObject, _assignmentClientMonitorSocket); } void AssignmentClient::sendAssignmentRequest() { @@ -188,9 +145,23 @@ void AssignmentClient::sendAssignmentRequest() { if (_assignmentServerHostname == "localhost") { // we want to check again for the local domain-server port in case the DS has restarted - quint16 localAssignmentServerPort; - if (nodeList->getLocalServerPortFromSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, _localASPortSharedMem, - localAssignmentServerPort)) { + if (!_localASPortSharedMem) { + _localASPortSharedMem = new QSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this); + + if (!_localASPortSharedMem->attach(QSharedMemory::ReadOnly)) { + qWarning() << "Could not attach to shared memory at key" << DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY + << "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort(); + } + } + + if (_localASPortSharedMem->isAttached()) { + _localASPortSharedMem->lock(); + + quint16 localAssignmentServerPort; + memcpy(&localAssignmentServerPort, _localASPortSharedMem->data(), sizeof(localAssignmentServerPort)); + + _localASPortSharedMem->unlock(); + if (localAssignmentServerPort != _assignmentServerSocket.getPort()) { qDebug() << "Port for local assignment server read from shared memory is" << localAssignmentServerPort; @@ -199,9 +170,7 @@ void AssignmentClient::sendAssignmentRequest() { nodeList->setAssignmentServerSocket(_assignmentServerSocket); } } - else { - qDebug () << "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort(); - } + } nodeList->sendAssignment(_requestAssignment); @@ -258,14 +227,6 @@ void AssignmentClient::readPendingDatagrams() { } else { qDebug() << "Received an assignment that could not be unpacked. Re-requesting."; } - } else if (packetTypeForPacket(receivedPacket) == PacketTypeStopNode) { - if (senderSockAddr.getAddress() == QHostAddress::LocalHost || - senderSockAddr.getAddress() == QHostAddress::LocalHostIPv6) { - qDebug() << "Network told me to exit."; - emit stopAssignmentClient(); - } else { - qDebug() << "Got a stop packet from other than localhost."; - } } else { // have the NodeList attempt to handle it nodeList->processNodeData(senderSockAddr, receivedPacket); diff --git a/assignment-client/src/AssignmentClient.h b/assignment-client/src/AssignmentClient.h index e105309e10..053458f136 100644 --- a/assignment-client/src/AssignmentClient.h +++ b/assignment-client/src/AssignmentClient.h @@ -29,22 +29,13 @@ private slots: void readPendingDatagrams(); void assignmentCompleted(); void handleAuthenticationRequest(); - void sendStatsPacketToACM(); - void stopAssignmentClient(); private: - void setUpStatsToMonitor(); Assignment _requestAssignment; static SharedAssignmentPointer _currentAssignment; QString _assignmentServerHostname; HifiSockAddr _assignmentServerSocket; - QSharedMemory* _localASPortSharedMem; // memory shared with domain server - QSharedMemory* _localACMPortSharedMem; // memory shared with assignment client monitor - QTimer _requestTimer; // timer for requesting and assignment - QTimer _statsTimerACM; // timer for sending stats to assignment client monitor - - protected: - HifiSockAddr _assignmentClientMonitorSocket; + QSharedMemory* _localASPortSharedMem; }; #endif // hifi_AssignmentClient_h diff --git a/assignment-client/src/AssignmentClientApp.cpp b/assignment-client/src/AssignmentClientApp.cpp deleted file mode 100644 index 477f1a2cf8..0000000000 --- a/assignment-client/src/AssignmentClientApp.cpp +++ /dev/null @@ -1,66 +0,0 @@ -// -// AssignmentClientapp.cpp -// assignment-client/src -// -// Created by Seth Alves on 2/19/15. -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include - -#include -#include - -#include "Assignment.h" -#include "AssignmentClient.h" -#include "AssignmentClientMonitor.h" -#include "AssignmentClientApp.h" - - -AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : - QCoreApplication(argc, argv) -{ -# ifndef WIN32 - setvbuf(stdout, NULL, _IOLBF, 0); -# endif - - // use the verbose message handler in Logging - qInstallMessageHandler(LogHandler::verboseMessageHandler); - - // parse command-line - QCommandLineParser parser; - parser.setApplicationDescription("High Fidelity Assignment Client"); - parser.addHelpOption(); - - const QCommandLineOption helpOption = parser.addHelpOption(); - - const QCommandLineOption numChildsOption("n", "number of children to fork", "child-count"); - parser.addOption(numChildsOption); - - if (!parser.parse(QCoreApplication::arguments())) { - qCritical() << parser.errorText() << endl; - parser.showHelp(); - Q_UNREACHABLE(); - } - - if (parser.isSet(helpOption)) { - parser.showHelp(); - Q_UNREACHABLE(); - } - - unsigned int numForks = 0; - if (parser.isSet(numChildsOption)) { - numForks = parser.value(numChildsOption).toInt(); - } - - if (numForks) { - AssignmentClientMonitor monitor(argc, argv, numForks); - monitor.exec(); - } else { - AssignmentClient client(argc, argv); - client.exec(); - } -} diff --git a/assignment-client/src/AssignmentClientApp.h b/assignment-client/src/AssignmentClientApp.h deleted file mode 100644 index c5099ff25c..0000000000 --- a/assignment-client/src/AssignmentClientApp.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// AssignmentClientapp.h -// assignment-client/src -// -// Created by Seth Alves on 2/19/15. -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include - -class AssignmentClientApp : public QCoreApplication { - Q_OBJECT -public: - AssignmentClientApp(int argc, char* argv[]); -}; diff --git a/assignment-client/src/AssignmentClientChildData.cpp b/assignment-client/src/AssignmentClientChildData.cpp deleted file mode 100644 index de34613ec9..0000000000 --- a/assignment-client/src/AssignmentClientChildData.cpp +++ /dev/null @@ -1,8 +0,0 @@ - -#include "AssignmentClientChildData.h" - - -AssignmentClientChildData::AssignmentClientChildData(QString childType) : - _childType(childType) -{ -} diff --git a/assignment-client/src/AssignmentClientChildData.h b/assignment-client/src/AssignmentClientChildData.h deleted file mode 100644 index 6fd5f72f7f..0000000000 --- a/assignment-client/src/AssignmentClientChildData.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// AssignmentClientChildData.h -// assignment-client/src -// -// Created by Seth Alves on 2/23/2015. -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_AssignmentClientChildData_h -#define hifi_AssignmentClientChildData_h - -#include - - -class AssignmentClientChildData : public NodeData { - public: - AssignmentClientChildData(QString childType); - - QString getChildType() { return _childType; } - void setChildType(QString childType) { _childType = childType; } - - // implement parseData to return 0 so we can be a subclass of NodeData - int parseData(const QByteArray& packet) { return 0; } - - private: - QString _childType; -}; - -#endif // hifi_AssignmentClientChildData_h diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 803c7fd5c7..45e1f56d53 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -13,18 +13,14 @@ #include #include -#include #include "AssignmentClientMonitor.h" -#include "AssignmentClientChildData.h" -#include "PacketHeaders.h" -#include "SharedUtil.h" const char* NUM_FORKS_PARAMETER = "-n"; const QString ASSIGNMENT_CLIENT_MONITOR_TARGET_NAME = "assignment-client-monitor"; -AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, const unsigned int numAssignmentClientForks) : +AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, int numAssignmentClientForks) : QCoreApplication(argc, argv) { // start the Logging class with the parent's target name @@ -45,25 +41,11 @@ AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, const u // this removes both the "-n" parameter and the number of forks passed _childArguments.removeAt(forksParameterIndex); _childArguments.removeAt(forksParameterIndex); - - - // create a NodeList so we can receive stats from children - DependencyManager::registerInheritance(); - auto addressManager = DependencyManager::set(); - auto nodeList = DependencyManager::set(DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT, - DEFAULT_ASSIGNMENT_CLIENT_MONITOR_DTLS_PORT); - - connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClientMonitor::readPendingDatagrams); - - nodeList->putLocalPortIntoSharedMemory(ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY, this); // use QProcess to fork off a process for each of the child assignment clients - for (unsigned int i = 0; i < numAssignmentClientForks; i++) { + for (int i = 0; i < numAssignmentClientForks; i++) { spawnChildClient(); } - - connect(&_checkSparesTimer, SIGNAL(timeout()), SLOT(checkSpares())); - _checkSparesTimer.start(NODE_SILENCE_THRESHOLD_MSECS * 3); } AssignmentClientMonitor::~AssignmentClientMonitor() { @@ -71,122 +53,46 @@ AssignmentClientMonitor::~AssignmentClientMonitor() { } void AssignmentClientMonitor::stopChildProcesses() { - auto nodeList = DependencyManager::get(); - - nodeList->eachNode([&](const SharedNodePointer& node) { - qDebug() << "asking child" << node->getUUID() << "to exit."; - node->activateLocalSocket(); - QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); - nodeList->writeUnverifiedDatagram(diePacket, *node->getActiveSocket()); - }); + + QList >::Iterator it = _childProcesses.begin(); + while (it != _childProcesses.end()) { + if (!it->isNull()) { + qDebug() << "Monitor is terminating child process" << it->data(); + + // don't re-spawn this child when it goes down + disconnect(it->data(), 0, this, 0); + + it->data()->terminate(); + it->data()->waitForFinished(); + } + + it = _childProcesses.erase(it); + } } void AssignmentClientMonitor::spawnChildClient() { QProcess *assignmentClient = new QProcess(this); + _childProcesses.append(QPointer(assignmentClient)); + // make sure that the output from the child process appears in our output assignmentClient->setProcessChannelMode(QProcess::ForwardedChannels); assignmentClient->start(applicationFilePath(), _childArguments); - + + // link the child processes' finished slot to our childProcessFinished slot + connect(assignmentClient, SIGNAL(finished(int, QProcess::ExitStatus)), this, + SLOT(childProcessFinished(int, QProcess::ExitStatus))); + qDebug() << "Spawned a child client with PID" << assignmentClient->pid(); } - - -void AssignmentClientMonitor::checkSpares() { - auto nodeList = DependencyManager::get(); - QUuid aSpareId = ""; - unsigned int spareCount = 0; - - nodeList->removeSilentNodes(); - - nodeList->eachNode([&](const SharedNodePointer& node) { - AssignmentClientChildData *childData = static_cast(node->getLinkedData()); - if (childData->getChildType() == "none") { - spareCount ++; - aSpareId = node->getUUID(); - } - }); - - if (spareCount != 1) { - qDebug() << "spare count is" << spareCount; - } - - if (spareCount < 1) { - spawnChildClient(); - } - - if (spareCount > 1) { - // kill aSpareId - qDebug() << "asking child" << aSpareId << "to exit."; - SharedNodePointer childNode = nodeList->nodeWithUUID(aSpareId); - childNode->activateLocalSocket(); - QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); - nodeList->writeUnverifiedDatagram(diePacket, childNode); - } +void AssignmentClientMonitor::childProcessFinished(int exitCode, QProcess::ExitStatus exitStatus) { + qDebug("Replacing dead child assignment client with a new one"); + + // remove the old process from our list of child processes + qDebug() << "need to remove" << QPointer(qobject_cast(sender())); + _childProcesses.removeOne(QPointer(qobject_cast(sender()))); + + spawnChildClient(); } - - -void AssignmentClientMonitor::readPendingDatagrams() { - auto nodeList = DependencyManager::get(); - - QByteArray receivedPacket; - HifiSockAddr senderSockAddr; - - while (nodeList->getNodeSocket().hasPendingDatagrams()) { - receivedPacket.resize(nodeList->getNodeSocket().pendingDatagramSize()); - nodeList->getNodeSocket().readDatagram(receivedPacket.data(), receivedPacket.size(), - senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer()); - - if (nodeList->packetVersionAndHashMatch(receivedPacket)) { - if (packetTypeForPacket(receivedPacket) == PacketTypeNodeJsonStats) { - QUuid packetUUID = uuidFromPacketHeader(receivedPacket); - SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(receivedPacket); - if (!matchingNode) { - // The parent only expects to be talking with prorams running on this same machine. - if (senderSockAddr.getAddress() == QHostAddress::LocalHost || - senderSockAddr.getAddress() == QHostAddress::LocalHostIPv6) { - if (!packetUUID.isNull()) { - matchingNode = DependencyManager::get()->addOrUpdateNode - (packetUUID, NodeType::Unassigned, senderSockAddr, senderSockAddr, false); - AssignmentClientChildData *childData = new AssignmentClientChildData("unknown"); - matchingNode->setLinkedData(childData); - } else { - // tell unknown assignment-client child to exit. - qDebug() << "asking unknown child to exit."; - QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); - nodeList->writeUnverifiedDatagram(diePacket, senderSockAddr); - } - } - } - - if (matchingNode) { - // update our records about how to reach this child - matchingNode->setLocalSocket(senderSockAddr); - - // push past the packet header - QDataStream packetStream(receivedPacket); - packetStream.skipRawData(numBytesForPacketHeader(receivedPacket)); - // decode json - QVariantMap unpackedVariantMap; - packetStream >> unpackedVariantMap; - QJsonObject unpackedStatsJSON = QJsonObject::fromVariantMap(unpackedVariantMap); - - // get child's assignment type out of the decoded json - QString childType = unpackedStatsJSON["assignment_type"].toString(); - AssignmentClientChildData *childData = - static_cast(matchingNode->getLinkedData()); - childData->setChildType(childType); - // note when this child talked - matchingNode->setLastHeardMicrostamp(usecTimestampNow()); - } - } else { - // have the NodeList attempt to handle it - nodeList->processNodeData(senderSockAddr, receivedPacket); - } - } - } -} - - diff --git a/assignment-client/src/AssignmentClientMonitor.h b/assignment-client/src/AssignmentClientMonitor.h index 71ae34bc8c..9a7bca9cb3 100644 --- a/assignment-client/src/AssignmentClientMonitor.h +++ b/assignment-client/src/AssignmentClientMonitor.h @@ -15,30 +15,25 @@ #include #include #include -#include #include -#include "AssignmentClientChildData.h" - extern const char* NUM_FORKS_PARAMETER; - class AssignmentClientMonitor : public QCoreApplication { Q_OBJECT public: - AssignmentClientMonitor(int &argc, char **argv, const unsigned int numAssignmentClientForks); + AssignmentClientMonitor(int &argc, char **argv, int numAssignmentClientForks); ~AssignmentClientMonitor(); void stopChildProcesses(); private slots: - void readPendingDatagrams(); - void checkSpares(); - + void childProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); private: void spawnChildClient(); + QList > _childProcesses; + QStringList _childArguments; - QTimer _checkSparesTimer; // every few seconds see if it need fewer or more spare children }; #endif // hifi_AssignmentClientMonitor_h diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index 81a12526bf..3bf6990a74 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -9,10 +9,34 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include +#include -#include "AssignmentClientApp.h" +#include "Assignment.h" +#include "AssignmentClient.h" +#include "AssignmentClientMonitor.h" int main(int argc, char* argv[]) { - AssignmentClientApp app(argc, argv); - return 0; +#ifndef WIN32 + setvbuf(stdout, NULL, _IOLBF, 0); +#endif + + // use the verbose message handler in Logging + qInstallMessageHandler(LogHandler::verboseMessageHandler); + + const char* numForksString = getCmdOption(argc, (const char**)argv, NUM_FORKS_PARAMETER); + + int numForks = 0; + + if (numForksString) { + numForks = atoi(numForksString); + } + + if (numForks) { + AssignmentClientMonitor monitor(argc, argv, numForks); + return monitor.exec(); + } else { + AssignmentClient client(argc, argv); + return client.exec(); + } } diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 64e0d335b1..f84722a438 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -246,7 +246,19 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) { auto nodeList = DependencyManager::set(domainServerPort, domainServerDTLSPort); // no matter the local port, save it to shared mem so that local assignment clients can ask what it is - nodeList->putLocalPortIntoSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this); + QSharedMemory* sharedPortMem = new QSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this); + quint16 localPort = nodeList->getNodeSocket().localPort(); + + // attempt to create the shared memory segment + if (sharedPortMem->create(sizeof(localPort)) || sharedPortMem->attach()) { + sharedPortMem->lock(); + memcpy(sharedPortMem->data(), &localPort, sizeof(localPort)); + sharedPortMem->unlock(); + + qDebug() << "Wrote local listening port" << localPort << "to shared memory at key" << DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY; + } else { + qWarning() << "Failed to create and attach to shared memory to share local port with assignment-client children."; + } // set our LimitedNodeList UUID to match the UUID from our config // nodes will currently use this to add resources to data-web that relate to our domain diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index f67abdca2b..9bcdcbe9a4 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -76,7 +76,7 @@ const QString AddressManager::currentPath(bool withOrientation) const { pathString += "/" + orientationString; } else { qDebug() << "Cannot add orientation to path without a getter for position." - << "Call AddressManager::setOrientationGetter to pass a function that will return a glm::quat"; + << "Call AdressManager::setOrientationGetter to pass a function that will return a glm::quat"; } } @@ -84,7 +84,7 @@ const QString AddressManager::currentPath(bool withOrientation) const { return pathString; } else { qDebug() << "Cannot create address path without a getter for position." - << "Call AddressManager::setPositionGetter to pass a function that will return a const glm::vec3&"; + << "Call AdressManager::setPositionGetter to pass a function that will return a const glm::vec3&"; return QString(); } } diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index b240f0df9e..c8c454ff14 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -669,41 +669,3 @@ void LimitedNodeList::sendHeartbeatToIceServer(const HifiSockAddr& iceServerSock writeUnverifiedDatagram(iceRequestByteArray, iceServerSockAddr); } - -void LimitedNodeList::putLocalPortIntoSharedMemory(const QString key, QObject* parent) { - // save our local port to shared memory so that assignment client children know how to talk to this parent - QSharedMemory* sharedPortMem = new QSharedMemory(key, parent); - quint16 localPort = getNodeSocket().localPort(); - - // attempt to create the shared memory segment - if (sharedPortMem->create(sizeof(localPort)) || sharedPortMem->attach()) { - sharedPortMem->lock(); - memcpy(sharedPortMem->data(), &localPort, sizeof(localPort)); - sharedPortMem->unlock(); - - qDebug() << "Wrote local listening port" << localPort << "to shared memory at key" << key; - } else { - qWarning() << "Failed to create and attach to shared memory to share local port with assignment-client children."; - } -} - - -bool LimitedNodeList::getLocalServerPortFromSharedMemory(const QString key, QSharedMemory*& sharedMem, - quint16& localPort) { - if (!sharedMem) { - sharedMem = new QSharedMemory(key, this); - - if (!sharedMem->attach(QSharedMemory::ReadOnly)) { - qWarning() << "Could not attach to shared memory at key" << key; - } - } - - if (sharedMem->isAttached()) { - sharedMem->lock(); - memcpy(&localPort, sharedMem->data(), sizeof(localPort)); - sharedMem->unlock(); - return true; - } - - return false; -} diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 02234ee4f7..72aefdb2b3 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -26,7 +26,6 @@ #include #include #include -#include #include @@ -50,11 +49,6 @@ const char STUN_SERVER_HOSTNAME[] = "stun.highfidelity.io"; const unsigned short STUN_SERVER_PORT = 3478; const QString DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY = "domain-server.local-port"; -const QString ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY = "assignment-client-monitor.local-port"; - -const char DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME[] = "localhost"; -const unsigned short DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT = 40104; -const unsigned short DEFAULT_ASSIGNMENT_CLIENT_MONITOR_DTLS_PORT = 40105; class HifiSockAddr; @@ -174,9 +168,6 @@ public: return SharedNodePointer(); } - - void putLocalPortIntoSharedMemory(const QString key, QObject* parent); - bool getLocalServerPortFromSharedMemory(const QString key, QSharedMemory*& sharedMem, quint16& localPort); public slots: void reset(); diff --git a/libraries/networking/src/Node.cpp b/libraries/networking/src/Node.cpp index 2a38799707..2bf792c6ee 100644 --- a/libraries/networking/src/Node.cpp +++ b/libraries/networking/src/Node.cpp @@ -149,12 +149,7 @@ QDataStream& operator>>(QDataStream& in, Node& node) { } QDebug operator<<(QDebug debug, const Node &node) { - debug.nospace() << NodeType::getNodeTypeName(node.getType()); - if (node.getType() == NodeType::Unassigned) { - debug.nospace() << " (1)"; - } else { - debug.nospace() << " (" << node.getType() << ")"; - } + debug.nospace() << NodeType::getNodeTypeName(node.getType()) << " (" << node.getType() << ")"; debug << " " << node.getUUID().toString().toLocal8Bit().constData() << " "; debug.nospace() << node.getPublicSocket() << "/" << node.getLocalSocket(); return debug.nospace(); diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index e63f230f6e..f70c2d9b3c 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -62,17 +62,13 @@ NodeList::NodeList(char newOwnerType, unsigned short socketListenPort, unsigned connect(&AccountManager::getInstance(), &AccountManager::logoutComplete , this, &NodeList::reset); } -qint64 NodeList::sendStats(const QJsonObject& statsObject, HifiSockAddr destination) { +qint64 NodeList::sendStatsToDomainServer(const QJsonObject& statsObject) { QByteArray statsPacket = byteArrayWithPopulatedHeader(PacketTypeNodeJsonStats); QDataStream statsPacketStream(&statsPacket, QIODevice::Append); statsPacketStream << statsObject.toVariantMap(); - return writeUnverifiedDatagram(statsPacket, destination); -} - -qint64 NodeList::sendStatsToDomainServer(const QJsonObject& statsObject) { - return sendStats(statsObject, _domainHandler.getSockAddr()); + return writeUnverifiedDatagram(statsPacket, _domainHandler.getSockAddr()); } void NodeList::timePingReply(const QByteArray& packet, const SharedNodePointer& sendingNode) { diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index 1c6de4bb6c..907fccfcac 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -47,7 +47,6 @@ public: NodeType_t getOwnerType() const { return _ownerType; } void setOwnerType(NodeType_t ownerType) { _ownerType = ownerType; } - qint64 sendStats(const QJsonObject& statsObject, HifiSockAddr destination); qint64 sendStatsToDomainServer(const QJsonObject& statsObject); int getNumNoReplyDomainCheckIns() const { return _numNoReplyDomainCheckIns; } diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index db97e216ee..2eee540fff 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -70,8 +70,6 @@ PacketVersion versionForPacketType(PacketType type) { return 2; case PacketTypeOctreeStats: return 1; - case PacketTypeStopNode: - return 1; case PacketTypeEntityAddOrEdit: case PacketTypeEntityData: return VERSION_MODEL_ENTITIES_SUPPORT_SHAPE_TYPE; @@ -126,7 +124,6 @@ QString nameForPacketType(PacketType type) { PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityErase); PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityAddResponse); PACKET_TYPE_NAME_LOOKUP(PacketTypeOctreeDataNack); - PACKET_TYPE_NAME_LOOKUP(PacketTypeStopNode); PACKET_TYPE_NAME_LOOKUP(PacketTypeAudioEnvironment); PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityEditNack); PACKET_TYPE_NAME_LOOKUP(PacketTypeSignedTransactionPayment); diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index 32f33c01d9..e593955b51 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -67,7 +67,7 @@ enum PacketType { PacketTypeEntityErase, PacketTypeEntityAddResponse, PacketTypeOctreeDataNack, // 45 - PacketTypeStopNode, + UNUSED_10, PacketTypeAudioEnvironment, PacketTypeEntityEditNack, PacketTypeSignedTransactionPayment, @@ -86,7 +86,7 @@ const QSet NON_VERIFIED_PACKETS = QSet() << PacketTypeNodeJsonStats << PacketTypeEntityQuery << PacketTypeOctreeDataNack << PacketTypeEntityEditNack << PacketTypeIceServerHeartbeat << PacketTypeIceServerHeartbeatResponse - << PacketTypeUnverifiedPing << PacketTypeUnverifiedPingReply << PacketTypeStopNode; + << PacketTypeUnverifiedPing << PacketTypeUnverifiedPingReply; const int NUM_BYTES_MD5_HASH = 16; const int NUM_STATIC_HEADER_BYTES = sizeof(PacketVersion) + NUM_BYTES_RFC4122_UUID;