From 7a3826b72a7fea97770065244812e1b225bff963 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 15 May 2014 14:35:01 -0700 Subject: [PATCH 01/11] Add Node border display --- interface/src/Application.cpp | 5 + interface/src/Application.h | 7 +- interface/src/Menu.cpp | 13 +++ interface/src/Menu.h | 3 + interface/src/ui/NodeBounds.cpp | 190 ++++++++++++++++++++++++++++++++ interface/src/ui/NodeBounds.h | 45 ++++++++ 6 files changed, 262 insertions(+), 1 deletion(-) create mode 100644 interface/src/ui/NodeBounds.cpp create mode 100644 interface/src/ui/NodeBounds.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fb414311ef..fa19fd620b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -169,6 +169,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _bytesPerSecond(0), _previousScriptLocation(), _logger(new FileLogger(this)), + _nodeBoundsDisplay(this), _runningScriptsWidget(new RunningScriptsWidget(_window)), _runningScriptsWidgetWasVisible(false) { @@ -2556,6 +2557,9 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { // restore default, white specular glMaterialfv(GL_FRONT, GL_SPECULAR, WHITE_SPECULAR_COLOR); + + _nodeBoundsDisplay.draw(); + } bool mirrorMode = (whichCamera.getInterpolatedMode() == CAMERA_MODE_MIRROR); @@ -2792,6 +2796,7 @@ void Application::displayOverlay() { ? 80 : 20; drawText(_glWidget->width() - 100, _glWidget->height() - timerBottom, 0.30f, 0.0f, 0, frameTimer, WHITE_TEXT); } + _nodeBoundsDisplay.drawOverlay(); _overlays.render2D(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 54e6bcdcac..8a685b9643 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -72,6 +72,7 @@ #include "ui/BandwidthDialog.h" #include "ui/BandwidthMeter.h" #include "ui/ModelsBrowser.h" +#include "ui/NodeBounds.h" #include "ui/OctreeStatsDialog.h" #include "ui/RearMirrorTools.h" #include "ui/LodToolsDialog.h" @@ -189,6 +190,8 @@ public: bool isMouseHidden() const { return _mouseHidden; } const glm::vec3& getMouseRayOrigin() const { return _mouseRayOrigin; } const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; } + int getMouseX() const { return _mouseX; } + int getMouseY() const { return _mouseY; } Faceplus* getFaceplus() { return &_faceplus; } Faceshift* getFaceshift() { return &_faceshift; } Visage* getVisage() { return &_visage; } @@ -242,7 +245,7 @@ public: void computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& nearVal, float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const; - + NodeBounds& getNodeBoundsDisplay() { return _nodeBoundsDisplay; } VoxelShader& getVoxelShader() { return _voxelShader; } PointShader& getPointShader() { return _pointShader; } @@ -520,6 +523,8 @@ private: NodeToOctreeSceneStats _octreeServerSceneStats; QReadWriteLock _octreeSceneStatsLock; + NodeBounds _nodeBoundsDisplay; + std::vector _voxelFades; ControllerScriptingInterface _controllerScriptingInterface; QPointer _logDialog; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index ad2b220d55..c0e1ab54a2 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -42,6 +42,7 @@ #include "ui/MetavoxelEditor.h" #include "ui/ModelsBrowser.h" #include "ui/LoginDialog.h" +#include "ui/NodeBounds.h" Menu* Menu::_instance = NULL; @@ -242,6 +243,18 @@ Menu::Menu() : SLOT(setEnable3DTVMode(bool))); + NodeBounds& nodeBounds = appInstance->getNodeBoundsDisplay(); + addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::ShowBordersVoxelNodes, + Qt::CTRL | Qt::SHIFT | Qt::Key_1, false, + &nodeBounds, SLOT(setShowVoxelNodes(bool))); + addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::ShowBordersModelNodes, + Qt::CTRL | Qt::SHIFT | Qt::Key_2, false, + &nodeBounds, SLOT(setShowModelNodes(bool))); + addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::ShowBordersParticleNodes, + Qt::CTRL | Qt::SHIFT | Qt::Key_3, false, + &nodeBounds, SLOT(setShowParticleNodes(bool))); + + QMenu* avatarSizeMenu = viewMenu->addMenu("Avatar Size"); addActionToQMenuAndActionHash(avatarSizeMenu, diff --git a/interface/src/Menu.h b/interface/src/Menu.h index f1d35fcb81..b108ff8e46 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -367,6 +367,9 @@ namespace MenuOption { const QString SettingsExport = "Export Settings"; const QString SettingsImport = "Import Settings"; const QString Shadows = "Shadows"; + const QString ShowBordersVoxelNodes = "Show Borders - Voxel Nodes"; + const QString ShowBordersModelNodes = "Show Borders - Model Nodes"; + const QString ShowBordersParticleNodes = "Show Borders - Particle Nodes"; const QString ShowCulledSharedFaces = "Show Culled Shared Voxel Faces"; const QString ShowIKConstraints = "Show IK Constraints"; const QString Stars = "Stars"; diff --git a/interface/src/ui/NodeBounds.cpp b/interface/src/ui/NodeBounds.cpp new file mode 100644 index 0000000000..ffdf52514e --- /dev/null +++ b/interface/src/ui/NodeBounds.cpp @@ -0,0 +1,190 @@ +// +// NodeBounds.cpp +// interface/src/ui +// +// Created by Ryan Huffman on 05/14/14. +// Copyright 2014 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 "Application.h" +#include "NodeBounds.h" +#include "Util.h" + +NodeBounds::NodeBounds(QObject* parent) : + QObject(parent), + _showVoxelNodes(false), + _showModelNodes(false), + _showParticleNodes(false), + _overlayText("") { + +} + +void NodeBounds::draw() { + NodeToJurisdictionMap& voxelServerJurisdictions = Application::getInstance()->getVoxelServerJurisdictions(); + NodeToJurisdictionMap& modelServerJurisdictions = Application::getInstance()->getModelServerJurisdictions(); + NodeToJurisdictionMap& particleServerJurisdictions = Application::getInstance()->getParticleServerJurisdictions(); + NodeToJurisdictionMap* serverJurisdictions; + + Application* application = Application::getInstance(); + const glm::vec3& mouseRayOrigin = application->getMouseRayOrigin(); + const glm::vec3& mouseRayDirection = application->getMouseRayDirection(); + + float closest = FLT_MAX; + glm::vec3 closestCenter; + float closestScale = 0; + bool closestIsInside = true; + Node* closestNode = NULL; + bool isSelecting = false; + + int num = 0; + NodeList* nodeList = NodeList::getInstance(); + + foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { + NodeType_t nodeType = node->getType(); + + float r = nodeType == NodeType::VoxelServer ? 1.0 : 0.0; + float g = nodeType == NodeType::ParticleServer ? 1.0 : 0.0; + float b = nodeType == NodeType::ModelServer ? 1.0 : 0.0; + + if (nodeType == NodeType::VoxelServer && _showVoxelNodes) { + serverJurisdictions = &voxelServerJurisdictions; + } else if (nodeType == NodeType::ModelServer && _showModelNodes) { + serverJurisdictions = &modelServerJurisdictions; + } else if (nodeType == NodeType::ParticleServer && _showParticleNodes) { + serverJurisdictions = &particleServerJurisdictions; + } else { + continue; + } + + QUuid nodeUUID = node->getUUID(); + if (serverJurisdictions->find(nodeUUID) != serverJurisdictions->end()) { + const JurisdictionMap& map = serverJurisdictions->value(nodeUUID); + + unsigned char* rootCode = map.getRootOctalCode(); + + if (rootCode) { + VoxelPositionSize rootDetails; + voxelDetailsForCode(rootCode, rootDetails); + glm::vec3 location(rootDetails.x, rootDetails.y, rootDetails.z); + location *= (float)TREE_SCALE; + float len = rootDetails.s * TREE_SCALE; + AABox serverBounds(location, rootDetails.s * TREE_SCALE); + + glm::vec3 center = serverBounds.getVertex(BOTTOM_RIGHT_NEAR) + (serverBounds.getVertex(TOP_LEFT_FAR) - serverBounds.getVertex(BOTTOM_RIGHT_NEAR)) / 2.0f; + + float scaleFactor = rootDetails.s * TREE_SCALE; + scaleFactor *= rootDetails.s == 1 ? 1.05 : 0.95; + scaleFactor *= nodeType == NodeType::VoxelServer ? 1.0 : (nodeType == NodeType::ParticleServer ? 0.980 : 0.960); + + drawNodeBorder(center, scaleFactor, r, g, b); + + float distance; + BoxFace face; + bool inside = serverBounds.contains(mouseRayOrigin); + bool colliding = serverBounds.findRayIntersection(mouseRayOrigin, mouseRayDirection, distance, face); + + if (colliding && (!isSelecting || (!inside && (distance < closest || closestIsInside)))) { + closest = distance; + closestCenter = center; + closestScale = scaleFactor; + closestIsInside = inside; + closestNode = node.data(); + isSelecting = true; + } + } + } + } + + if (isSelecting) { + glPushMatrix(); + + glTranslatef(closestCenter.x, closestCenter.y, closestCenter.z); + glScalef(closestScale, closestScale, closestScale); + + NodeType_t selectedNodeType = closestNode->getType(); + float r = selectedNodeType == NodeType::VoxelServer ? 1.0 : 0.0; + float g = selectedNodeType == NodeType::ParticleServer ? 1.0 : 0.0; + float b = selectedNodeType == NodeType::ModelServer ? 1.0 : 0.0; + glColor4f(r, g, b, 0.2); + glutSolidCube(1.0); + + glPopMatrix(); + + HifiSockAddr addr = closestNode->getPublicSocket(); + _overlayText = QString("%1:%2") + .arg(addr.getAddress().toString()) + .arg(addr.getPort()); + } else { + _overlayText = QString(); + } +} + +void NodeBounds::drawNodeBorder(glm::vec3 center, float scale, float red, float green, float blue) { + glPushMatrix(); + + glTranslatef(center.x, center.y, center.z); + glScalef(scale, scale, scale); + + glLineWidth(2.5); + glColor3f(red, green, blue); + glBegin(GL_LINES); + + glVertex3f(-0.5, -0.5, -0.5); + glVertex3f( 0.5, -0.5, -0.5); + + glVertex3f(-0.5, -0.5, -0.5); + glVertex3f(-0.5, 0.5, -0.5); + + glVertex3f(-0.5, -0.5, -0.5); + glVertex3f(-0.5, -0.5, 0.5); + + glVertex3f(-0.5, 0.5, -0.5); + glVertex3f( 0.5, 0.5, -0.5); + + glVertex3f(-0.5, 0.5, -0.5); + glVertex3f(-0.5, 0.5, 0.5); + + + + glVertex3f( 0.5, 0.5, 0.5); + glVertex3f(-0.5, 0.5, 0.5); + + glVertex3f( 0.5, 0.5, 0.5); + glVertex3f( 0.5, -0.5, 0.5); + + glVertex3f( 0.5, 0.5, 0.5); + glVertex3f( 0.5, 0.5, -0.5); + + glVertex3f( 0.5, -0.5, 0.5); + glVertex3f(-0.5, -0.5, 0.5); + + glVertex3f( 0.5, -0.5, 0.5); + glVertex3f( 0.5, -0.5, -0.5); + + + glVertex3f( 0.5, 0.5, -0.5); + glVertex3f( 0.5, -0.5, -0.5); + + glVertex3f(-0.5, 0.5, 0.5); + glVertex3f(-0.5, -0.5, 0.5); + + glEnd(); + + glPopMatrix(); +} + +const float WHITE_TEXT[] = { 0.93f, 0.93f, 0.93f }; +void NodeBounds::drawOverlay() { + if (!_overlayText.isNull() && !_overlayText.isEmpty()) { + QGLWidget* glWidget = Application::getInstance()->getGLWidget(); + Application* application = Application::getInstance(); + drawText(application->getMouseX(), application->getMouseY(), 0.1f, 0.0f, 0, _overlayText.toLocal8Bit().data(), WHITE_TEXT); + // drawText(application->getMouseX(), application->getMouseY(), 0.1f, 0.0f, 0, "durr", WHITE_TEXT); + } +} diff --git a/interface/src/ui/NodeBounds.h b/interface/src/ui/NodeBounds.h new file mode 100644 index 0000000000..c4cd7002bd --- /dev/null +++ b/interface/src/ui/NodeBounds.h @@ -0,0 +1,45 @@ +// +// NodeBounds.h +// interface/src/ui +// +// Created by Ryan Huffman on 05/14/14. +// Copyright 2014 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_NodeBounds_h +#define hifi_NodeBounds_h + +#include + +class NodeBounds : public QObject { + Q_OBJECT +public: + NodeBounds(QObject* parent = NULL); + + bool getShowVoxelNodes() { return _showVoxelNodes; } + bool getShowModelNodes() { return _showModelNodes; } + bool getShowParticleNodes() { return _showParticleNodes; } + + void draw(); + void drawOverlay(); + +public slots: + void setShowVoxelNodes(bool value) { _showVoxelNodes = value; } + void setShowModelNodes(bool value) { _showModelNodes = value; } + void setShowParticleNodes(bool value) { _showParticleNodes = value; } + +protected: + void drawNodeBorder(glm::vec3 center, float scale, float red, float green, float blue); + +private: + bool _showVoxelNodes; + bool _showModelNodes; + bool _showParticleNodes; + QString _overlayText; + +}; + +#endif // hifi_NodeBounds_h From f646eda7aaf885f6681224d52ce80dde66911a4d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 16 May 2014 09:30:34 -0700 Subject: [PATCH 02/11] Move server borders to a submenu --- interface/src/Menu.cpp | 7 ++++--- interface/src/Menu.h | 6 +++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index a3a7faad2e..3084215d92 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -243,14 +243,15 @@ Menu::Menu() : SLOT(setEnable3DTVMode(bool))); + QMenu* nodeBordersMenu = viewMenu->addMenu("Server Borders"); NodeBounds& nodeBounds = appInstance->getNodeBoundsDisplay(); - addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::ShowBordersVoxelNodes, + addCheckableActionToQMenuAndActionHash(nodeBordersMenu, MenuOption::ShowBordersVoxelNodes, Qt::CTRL | Qt::SHIFT | Qt::Key_1, false, &nodeBounds, SLOT(setShowVoxelNodes(bool))); - addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::ShowBordersModelNodes, + addCheckableActionToQMenuAndActionHash(nodeBordersMenu, MenuOption::ShowBordersModelNodes, Qt::CTRL | Qt::SHIFT | Qt::Key_2, false, &nodeBounds, SLOT(setShowModelNodes(bool))); - addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::ShowBordersParticleNodes, + addCheckableActionToQMenuAndActionHash(nodeBordersMenu, MenuOption::ShowBordersParticleNodes, Qt::CTRL | Qt::SHIFT | Qt::Key_3, false, &nodeBounds, SLOT(setShowParticleNodes(bool))); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index b1be5f2cdb..6a1e8bbc05 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -366,9 +366,9 @@ namespace MenuOption { const QString SettingsExport = "Export Settings"; const QString SettingsImport = "Import Settings"; const QString Shadows = "Shadows"; - const QString ShowBordersVoxelNodes = "Show Borders - Voxel Nodes"; - const QString ShowBordersModelNodes = "Show Borders - Model Nodes"; - const QString ShowBordersParticleNodes = "Show Borders - Particle Nodes"; + const QString ShowBordersVoxelNodes = "Show Voxel Nodes"; + const QString ShowBordersModelNodes = "Show Model Nodes"; + const QString ShowBordersParticleNodes = "Show Particle Nodes"; const QString ShowIKConstraints = "Show IK Constraints"; const QString Stars = "Stars"; const QString Stats = "Stats"; From 8252b01e309c466f53addf6d9077c4083144dbd9 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 16 May 2014 09:31:36 -0700 Subject: [PATCH 03/11] Cleanup NodeBounds --- interface/src/ui/NodeBounds.cpp | 139 +++++++++++++++++++++----------- interface/src/ui/NodeBounds.h | 3 + 2 files changed, 94 insertions(+), 48 deletions(-) diff --git a/interface/src/ui/NodeBounds.cpp b/interface/src/ui/NodeBounds.cpp index ffdf52514e..96639c44e5 100644 --- a/interface/src/ui/NodeBounds.cpp +++ b/interface/src/ui/NodeBounds.cpp @@ -5,11 +5,13 @@ // Created by Ryan Huffman on 05/14/14. // Copyright 2014 High Fidelity, Inc. // +// This class draws a border around the different Voxel, Model, and Particle nodes on the current domain, +// and a semi-transparent cube around the currently mouse-overed node. +// // 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 "Application.h" @@ -26,32 +28,37 @@ NodeBounds::NodeBounds(QObject* parent) : } void NodeBounds::draw() { + if (!(_showVoxelNodes || _showModelNodes || _showParticleNodes)) { + return; + } + NodeToJurisdictionMap& voxelServerJurisdictions = Application::getInstance()->getVoxelServerJurisdictions(); NodeToJurisdictionMap& modelServerJurisdictions = Application::getInstance()->getModelServerJurisdictions(); NodeToJurisdictionMap& particleServerJurisdictions = Application::getInstance()->getParticleServerJurisdictions(); NodeToJurisdictionMap* serverJurisdictions; + // Compute ray to find selected nodes later on. We can't use the pre-computed ray in Application because it centers + // itself after the cursor disappears. Application* application = Application::getInstance(); - const glm::vec3& mouseRayOrigin = application->getMouseRayOrigin(); - const glm::vec3& mouseRayDirection = application->getMouseRayDirection(); + QGLWidget* glWidget = application->getGLWidget(); + float mouseX = application->getMouseX() / (float)glWidget->width(); + float mouseY = application->getMouseY() / (float)glWidget->height(); + glm::vec3 mouseRayOrigin; + glm::vec3 mouseRayDirection; + application->getViewFrustum()->computePickRay(mouseX, mouseY, mouseRayOrigin, mouseRayDirection); - float closest = FLT_MAX; - glm::vec3 closestCenter; - float closestScale = 0; - bool closestIsInside = true; - Node* closestNode = NULL; - bool isSelecting = false; + // Variables to keep track of the selected node and properties to draw the cube later if needed + Node* selectedNode = NULL; + float selectedDistance = FLT_MAX; + bool selectedIsInside = true; + glm::vec3 selectedCenter; + float selectedScale = 0; - int num = 0; NodeList* nodeList = NodeList::getInstance(); foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { NodeType_t nodeType = node->getType(); - float r = nodeType == NodeType::VoxelServer ? 1.0 : 0.0; - float g = nodeType == NodeType::ParticleServer ? 1.0 : 0.0; - float b = nodeType == NodeType::ModelServer ? 1.0 : 0.0; - if (nodeType == NodeType::VoxelServer && _showVoxelNodes) { serverJurisdictions = &voxelServerJurisdictions; } else if (nodeType == NodeType::ModelServer && _showModelNodes) { @@ -61,65 +68,85 @@ void NodeBounds::draw() { } else { continue; } - + QUuid nodeUUID = node->getUUID(); if (serverJurisdictions->find(nodeUUID) != serverJurisdictions->end()) { const JurisdictionMap& map = serverJurisdictions->value(nodeUUID); - + unsigned char* rootCode = map.getRootOctalCode(); - + if (rootCode) { VoxelPositionSize rootDetails; voxelDetailsForCode(rootCode, rootDetails); glm::vec3 location(rootDetails.x, rootDetails.y, rootDetails.z); location *= (float)TREE_SCALE; - float len = rootDetails.s * TREE_SCALE; + AABox serverBounds(location, rootDetails.s * TREE_SCALE); - glm::vec3 center = serverBounds.getVertex(BOTTOM_RIGHT_NEAR) + (serverBounds.getVertex(TOP_LEFT_FAR) - serverBounds.getVertex(BOTTOM_RIGHT_NEAR)) / 2.0f; + glm::vec3 center = serverBounds.getVertex(BOTTOM_RIGHT_NEAR) + + ((serverBounds.getVertex(TOP_LEFT_FAR) - serverBounds.getVertex(BOTTOM_RIGHT_NEAR)) / 2.0f); + + const float VOXEL_NODE_SCALE = 1.00f; + const float MODEL_NODE_SCALE = 0.99f; + const float PARTICLE_NODE_SCALE = 0.98f; float scaleFactor = rootDetails.s * TREE_SCALE; - scaleFactor *= rootDetails.s == 1 ? 1.05 : 0.95; - scaleFactor *= nodeType == NodeType::VoxelServer ? 1.0 : (nodeType == NodeType::ParticleServer ? 0.980 : 0.960); - drawNodeBorder(center, scaleFactor, r, g, b); + // Scale by 0.98 - 1.02 depending on the scale of the node. This allows smaller nodes to scale in + // a bit and not overlap larger nodes. + scaleFactor *= 0.92 + (rootDetails.s * 0.08); + + // Scale different node types slightly differently because it's common for them to overlap. + if (nodeType == NodeType::VoxelServer) { + scaleFactor *= VOXEL_NODE_SCALE; + } else if (nodeType == NodeType::ModelServer) { + scaleFactor *= MODEL_NODE_SCALE; + } else { + scaleFactor *= PARTICLE_NODE_SCALE; + } + + float red, green, blue; + getColorForNodeType(nodeType, red, green, blue); + drawNodeBorder(center, scaleFactor, red, green, blue); float distance; BoxFace face; bool inside = serverBounds.contains(mouseRayOrigin); bool colliding = serverBounds.findRayIntersection(mouseRayOrigin, mouseRayDirection, distance, face); - if (colliding && (!isSelecting || (!inside && (distance < closest || closestIsInside)))) { - closest = distance; - closestCenter = center; - closestScale = scaleFactor; - closestIsInside = inside; - closestNode = node.data(); - isSelecting = true; + // If the camera is inside a node it will be "selected" if you don't have your cursor over another node + // that you aren't inside. + if (colliding && (!selectedNode || (!inside && (distance < selectedDistance || selectedIsInside)))) { + selectedNode = node.data(); + selectedDistance = distance; + selectedIsInside = inside; + selectedCenter = center; + selectedScale = scaleFactor; } } } } - if (isSelecting) { + if (selectedNode) { glPushMatrix(); - glTranslatef(closestCenter.x, closestCenter.y, closestCenter.z); - glScalef(closestScale, closestScale, closestScale); + glTranslatef(selectedCenter.x, selectedCenter.y, selectedCenter.z); + glScalef(selectedScale, selectedScale, selectedScale); - NodeType_t selectedNodeType = closestNode->getType(); - float r = selectedNodeType == NodeType::VoxelServer ? 1.0 : 0.0; - float g = selectedNodeType == NodeType::ParticleServer ? 1.0 : 0.0; - float b = selectedNodeType == NodeType::ModelServer ? 1.0 : 0.0; - glColor4f(r, g, b, 0.2); + NodeType_t selectedNodeType = selectedNode->getType(); + float red, green, blue; + getColorForNodeType(selectedNode->getType(), red, green, blue); + + glColor4f(red, green, blue, 0.2); glutSolidCube(1.0); glPopMatrix(); - HifiSockAddr addr = closestNode->getPublicSocket(); - _overlayText = QString("%1:%2") + HifiSockAddr addr = selectedNode->getPublicSocket(); + _overlayText = QString("%1:%2 %3ms") .arg(addr.getAddress().toString()) - .arg(addr.getPort()); + .arg(addr.getPort()) + .arg(selectedNode->getPingMs()); } else { _overlayText = QString(); } @@ -131,7 +158,7 @@ void NodeBounds::drawNodeBorder(glm::vec3 center, float scale, float red, float glTranslatef(center.x, center.y, center.z); glScalef(scale, scale, scale); - glLineWidth(2.5); + glLineWidth(2.5); glColor3f(red, green, blue); glBegin(GL_LINES); @@ -150,8 +177,6 @@ void NodeBounds::drawNodeBorder(glm::vec3 center, float scale, float red, float glVertex3f(-0.5, 0.5, -0.5); glVertex3f(-0.5, 0.5, 0.5); - - glVertex3f( 0.5, 0.5, 0.5); glVertex3f(-0.5, 0.5, 0.5); @@ -167,7 +192,6 @@ void NodeBounds::drawNodeBorder(glm::vec3 center, float scale, float red, float glVertex3f( 0.5, -0.5, 0.5); glVertex3f( 0.5, -0.5, -0.5); - glVertex3f( 0.5, 0.5, -0.5); glVertex3f( 0.5, -0.5, -0.5); @@ -179,12 +203,31 @@ void NodeBounds::drawNodeBorder(glm::vec3 center, float scale, float red, float glPopMatrix(); } -const float WHITE_TEXT[] = { 0.93f, 0.93f, 0.93f }; +void NodeBounds::getColorForNodeType(NodeType_t nodeType, float& red, float& green, float& blue) { + red = nodeType == NodeType::VoxelServer ? 1.0 : 0.0; + green = nodeType == NodeType::ParticleServer ? 1.0 : 0.0; + blue = nodeType == NodeType::ModelServer ? 1.0 : 0.0; +} + void NodeBounds::drawOverlay() { if (!_overlayText.isNull() && !_overlayText.isEmpty()) { - QGLWidget* glWidget = Application::getInstance()->getGLWidget(); Application* application = Application::getInstance(); - drawText(application->getMouseX(), application->getMouseY(), 0.1f, 0.0f, 0, _overlayText.toLocal8Bit().data(), WHITE_TEXT); - // drawText(application->getMouseX(), application->getMouseY(), 0.1f, 0.0f, 0, "durr", WHITE_TEXT); + + const float TEXT_COLOR[] = { 0.90f, 0.90f, 0.90f }; + const float TEXT_SCALE = 0.1f; + const int TEXT_HEIGHT = 10; + const int PADDING = 10; + const int MOUSE_OFFSET = 10; + const int BACKGROUND_OFFSET_Y = -20; + const int BACKGROUND_BEVEL = 3; + + char* text = _overlayText.toLocal8Bit().data(); + int mouseX = application->getMouseX(), + mouseY = application->getMouseY(), + textWidth = widthText(TEXT_SCALE, 0, text); + glColor4f(0.4, 0.4, 0.4, 0.6); + renderBevelCornersRect(mouseX + MOUSE_OFFSET, mouseY - TEXT_HEIGHT - PADDING, + textWidth + (2 * PADDING), TEXT_HEIGHT + (2 * PADDING), BACKGROUND_BEVEL); + drawText(mouseX + MOUSE_OFFSET + PADDING, mouseY, TEXT_SCALE, 0.0f, 0, text, TEXT_COLOR); } } diff --git a/interface/src/ui/NodeBounds.h b/interface/src/ui/NodeBounds.h index c4cd7002bd..9ef2ab486a 100644 --- a/interface/src/ui/NodeBounds.h +++ b/interface/src/ui/NodeBounds.h @@ -14,6 +14,8 @@ #include +#include + class NodeBounds : public QObject { Q_OBJECT public: @@ -33,6 +35,7 @@ public slots: protected: void drawNodeBorder(glm::vec3 center, float scale, float red, float green, float blue); + void getColorForNodeType(NodeType_t nodeType, float& red, float& green, float& blue); private: bool _showVoxelNodes; From ea5dfbdf28f540373b3a67f6a02d0204a5c62dd5 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 16 May 2014 09:53:48 -0700 Subject: [PATCH 04/11] Update parameter to const --- interface/src/ui/NodeBounds.cpp | 4 ++-- interface/src/ui/NodeBounds.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/NodeBounds.cpp b/interface/src/ui/NodeBounds.cpp index 96639c44e5..4621be6c42 100644 --- a/interface/src/ui/NodeBounds.cpp +++ b/interface/src/ui/NodeBounds.cpp @@ -152,7 +152,7 @@ void NodeBounds::draw() { } } -void NodeBounds::drawNodeBorder(glm::vec3 center, float scale, float red, float green, float blue) { +void NodeBounds::drawNodeBorder(const glm::vec3& center, float scale, float red, float green, float blue) { glPushMatrix(); glTranslatef(center.x, center.y, center.z); @@ -221,7 +221,7 @@ void NodeBounds::drawOverlay() { const int BACKGROUND_OFFSET_Y = -20; const int BACKGROUND_BEVEL = 3; - char* text = _overlayText.toLocal8Bit().data(); + char* text = _overlayText.toLatin1().data(); int mouseX = application->getMouseX(), mouseY = application->getMouseY(), textWidth = widthText(TEXT_SCALE, 0, text); diff --git a/interface/src/ui/NodeBounds.h b/interface/src/ui/NodeBounds.h index 9ef2ab486a..ae2be5f2c1 100644 --- a/interface/src/ui/NodeBounds.h +++ b/interface/src/ui/NodeBounds.h @@ -34,7 +34,7 @@ public slots: void setShowParticleNodes(bool value) { _showParticleNodes = value; } protected: - void drawNodeBorder(glm::vec3 center, float scale, float red, float green, float blue); + void drawNodeBorder(const glm::vec3& center, float scale, float red, float green, float blue); void getColorForNodeType(NodeType_t nodeType, float& red, float& green, float& blue); private: From dbbd3351efa7d84bb613621b94c600ee9e65f4be Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 16 May 2014 10:10:50 -0700 Subject: [PATCH 05/11] Fix node bounds overlay blinking QString.to* do not seem to return null terminated strings. --- interface/src/ui/NodeBounds.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/NodeBounds.cpp b/interface/src/ui/NodeBounds.cpp index 4621be6c42..e1e37fe21b 100644 --- a/interface/src/ui/NodeBounds.cpp +++ b/interface/src/ui/NodeBounds.cpp @@ -216,18 +216,22 @@ void NodeBounds::drawOverlay() { const float TEXT_COLOR[] = { 0.90f, 0.90f, 0.90f }; const float TEXT_SCALE = 0.1f; const int TEXT_HEIGHT = 10; + const float ROTATION = 0.0f; + const int FONT = 2; const int PADDING = 10; const int MOUSE_OFFSET = 10; const int BACKGROUND_OFFSET_Y = -20; const int BACKGROUND_BEVEL = 3; - char* text = _overlayText.toLatin1().data(); + char textData[_overlayText.length() + 1]; + strcpy(textData, _overlayText.toLatin1().constData()); + int mouseX = application->getMouseX(), mouseY = application->getMouseY(), - textWidth = widthText(TEXT_SCALE, 0, text); + textWidth = widthText(TEXT_SCALE, 0, textData); glColor4f(0.4, 0.4, 0.4, 0.6); renderBevelCornersRect(mouseX + MOUSE_OFFSET, mouseY - TEXT_HEIGHT - PADDING, textWidth + (2 * PADDING), TEXT_HEIGHT + (2 * PADDING), BACKGROUND_BEVEL); - drawText(mouseX + MOUSE_OFFSET + PADDING, mouseY, TEXT_SCALE, 0.0f, 0, text, TEXT_COLOR); + drawText(mouseX + MOUSE_OFFSET + PADDING, mouseY, TEXT_SCALE, ROTATION, FONT, textData, TEXT_COLOR); } } From 91b1910b86c86f41cf7cedc911fe63d304e44403 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 16 May 2014 10:28:21 -0700 Subject: [PATCH 06/11] Explicitly null-terminate a string --- interface/src/ui/NodeBounds.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/NodeBounds.cpp b/interface/src/ui/NodeBounds.cpp index e1e37fe21b..40ae606733 100644 --- a/interface/src/ui/NodeBounds.cpp +++ b/interface/src/ui/NodeBounds.cpp @@ -223,8 +223,10 @@ void NodeBounds::drawOverlay() { const int BACKGROUND_OFFSET_Y = -20; const int BACKGROUND_BEVEL = 3; - char textData[_overlayText.length() + 1]; + int textLength = _overlayText.length(); + char textData[textLength + 1]; strcpy(textData, _overlayText.toLatin1().constData()); + textData[textLength] = '\0'; int mouseX = application->getMouseX(), mouseY = application->getMouseY(), From 59b23efbd84ccd926152a2e946f21a4f302aaa31 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 16 May 2014 10:37:28 -0700 Subject: [PATCH 07/11] Update old comment --- interface/src/ui/NodeBounds.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/NodeBounds.cpp b/interface/src/ui/NodeBounds.cpp index 40ae606733..b46b729157 100644 --- a/interface/src/ui/NodeBounds.cpp +++ b/interface/src/ui/NodeBounds.cpp @@ -92,7 +92,7 @@ void NodeBounds::draw() { float scaleFactor = rootDetails.s * TREE_SCALE; - // Scale by 0.98 - 1.02 depending on the scale of the node. This allows smaller nodes to scale in + // Scale by 0.92 - 1.00 depending on the scale of the node. This allows smaller nodes to scale in // a bit and not overlap larger nodes. scaleFactor *= 0.92 + (rootDetails.s * 0.08); From 32974b40032a29320cb0290e5ff26684a9b1b070 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 16 May 2014 12:16:42 -0700 Subject: [PATCH 08/11] Remove QGLWidget include from NodeBounds --- interface/src/ui/NodeBounds.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/interface/src/ui/NodeBounds.cpp b/interface/src/ui/NodeBounds.cpp index b46b729157..1f06f60c5c 100644 --- a/interface/src/ui/NodeBounds.cpp +++ b/interface/src/ui/NodeBounds.cpp @@ -12,8 +12,6 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include - #include "Application.h" #include "NodeBounds.h" #include "Util.h" From 3f2d08871cef7ddf57fdab915b78a4604031a8b2 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 16 May 2014 12:24:26 -0700 Subject: [PATCH 09/11] Reorder includes in NodeBounds.cpp --- interface/src/ui/NodeBounds.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/NodeBounds.cpp b/interface/src/ui/NodeBounds.cpp index 1f06f60c5c..6d4d809a86 100644 --- a/interface/src/ui/NodeBounds.cpp +++ b/interface/src/ui/NodeBounds.cpp @@ -13,9 +13,10 @@ // #include "Application.h" -#include "NodeBounds.h" #include "Util.h" +#include "NodeBounds.h" + NodeBounds::NodeBounds(QObject* parent) : QObject(parent), _showVoxelNodes(false), From e5d6a66ca9dd354b8d4b15ae80b293c02b5b9beb Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 16 May 2014 13:21:10 -0700 Subject: [PATCH 10/11] Use char array instead of QString in NodeBounds --- interface/src/ui/NodeBounds.cpp | 24 ++++++++++++------------ interface/src/ui/NodeBounds.h | 4 +++- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/interface/src/ui/NodeBounds.cpp b/interface/src/ui/NodeBounds.cpp index 40ae606733..a7d3ae062d 100644 --- a/interface/src/ui/NodeBounds.cpp +++ b/interface/src/ui/NodeBounds.cpp @@ -23,7 +23,7 @@ NodeBounds::NodeBounds(QObject* parent) : _showVoxelNodes(false), _showModelNodes(false), _showParticleNodes(false), - _overlayText("") { + _overlayText() { } @@ -143,12 +143,17 @@ void NodeBounds::draw() { glPopMatrix(); HifiSockAddr addr = selectedNode->getPublicSocket(); - _overlayText = QString("%1:%2 %3ms") + QString overlay = QString("%1:%2 %3ms") .arg(addr.getAddress().toString()) .arg(addr.getPort()) - .arg(selectedNode->getPingMs()); + .arg(selectedNode->getPingMs()) + .left(MAX_OVERLAY_TEXT_LENGTH); + + // Ideally we'd just use a QString, but I ran into weird blinking issues using + // constData() directly, as if the data was being overwritten. + strcpy(_overlayText, overlay.toLocal8Bit().constData()); } else { - _overlayText = QString(); + _overlayText[0] = '\0'; } } @@ -210,7 +215,7 @@ void NodeBounds::getColorForNodeType(NodeType_t nodeType, float& red, float& gre } void NodeBounds::drawOverlay() { - if (!_overlayText.isNull() && !_overlayText.isEmpty()) { + if (strlen(_overlayText) > 0) { Application* application = Application::getInstance(); const float TEXT_COLOR[] = { 0.90f, 0.90f, 0.90f }; @@ -223,17 +228,12 @@ void NodeBounds::drawOverlay() { const int BACKGROUND_OFFSET_Y = -20; const int BACKGROUND_BEVEL = 3; - int textLength = _overlayText.length(); - char textData[textLength + 1]; - strcpy(textData, _overlayText.toLatin1().constData()); - textData[textLength] = '\0'; - int mouseX = application->getMouseX(), mouseY = application->getMouseY(), - textWidth = widthText(TEXT_SCALE, 0, textData); + textWidth = widthText(TEXT_SCALE, 0, _overlayText); glColor4f(0.4, 0.4, 0.4, 0.6); renderBevelCornersRect(mouseX + MOUSE_OFFSET, mouseY - TEXT_HEIGHT - PADDING, textWidth + (2 * PADDING), TEXT_HEIGHT + (2 * PADDING), BACKGROUND_BEVEL); - drawText(mouseX + MOUSE_OFFSET + PADDING, mouseY, TEXT_SCALE, ROTATION, FONT, textData, TEXT_COLOR); + drawText(mouseX + MOUSE_OFFSET + PADDING, mouseY, TEXT_SCALE, ROTATION, FONT, _overlayText, TEXT_COLOR); } } diff --git a/interface/src/ui/NodeBounds.h b/interface/src/ui/NodeBounds.h index ae2be5f2c1..bd54b84e98 100644 --- a/interface/src/ui/NodeBounds.h +++ b/interface/src/ui/NodeBounds.h @@ -16,6 +16,8 @@ #include +const int MAX_OVERLAY_TEXT_LENGTH = 64; + class NodeBounds : public QObject { Q_OBJECT public: @@ -41,7 +43,7 @@ private: bool _showVoxelNodes; bool _showModelNodes; bool _showParticleNodes; - QString _overlayText; + char _overlayText[MAX_OVERLAY_TEXT_LENGTH + 1]; }; From cc952f9cee0fc5ba7f65560bdaa4814c1db70620 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 16 May 2014 13:56:28 -0700 Subject: [PATCH 11/11] Reset node bounds overlay text when no nodes are selected --- interface/src/ui/NodeBounds.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/ui/NodeBounds.cpp b/interface/src/ui/NodeBounds.cpp index 581093e4c2..735dc66ddf 100644 --- a/interface/src/ui/NodeBounds.cpp +++ b/interface/src/ui/NodeBounds.cpp @@ -28,6 +28,7 @@ NodeBounds::NodeBounds(QObject* parent) : void NodeBounds::draw() { if (!(_showVoxelNodes || _showModelNodes || _showParticleNodes)) { + _overlayText[0] = '\0'; return; }