From bc516c0b865c3eab256299fd5e198a5de4c3b2ae Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 6 Nov 2015 11:32:56 -0800 Subject: [PATCH 01/61] use render-item status getters to display physics debugging information --- .../src/RenderableBoxEntityItem.cpp | 3 - .../src/RenderableDebugableEntityItem.cpp | 67 ------------------- .../src/RenderableDebugableEntityItem.h | 23 ------- .../src/RenderableLineEntityItem.cpp | 2 - .../src/RenderableLineEntityItem.h | 1 - .../src/RenderableModelEntityItem.cpp | 27 ++++++-- .../src/RenderableModelEntityItem.h | 1 - .../src/RenderablePolyLineEntityItem.cpp | 2 - .../src/RenderablePolyLineEntityItem.h | 1 - .../src/RenderablePolyVoxEntityItem.cpp | 2 - .../src/RenderablePolyVoxEntityItem.h | 1 - .../src/RenderableSphereEntityItem.cpp | 4 -- 12 files changed, 21 insertions(+), 113 deletions(-) delete mode 100644 libraries/entities-renderer/src/RenderableDebugableEntityItem.cpp delete mode 100644 libraries/entities-renderer/src/RenderableDebugableEntityItem.h diff --git a/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp b/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp index 077f28350b..5d82311bcc 100644 --- a/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp @@ -20,7 +20,6 @@ #include #include -#include "RenderableDebugableEntityItem.h" #include "../render-utils/simple_vert.h" #include "../render-utils/simple_frag.h" @@ -63,6 +62,4 @@ void RenderableBoxEntityItem::render(RenderArgs* args) { } else { DependencyManager::get()->renderSolidCubeInstance(batch, getTransformToCenter(), cubeColor); } - - RenderableDebugableEntityItem::render(this, args); }; diff --git a/libraries/entities-renderer/src/RenderableDebugableEntityItem.cpp b/libraries/entities-renderer/src/RenderableDebugableEntityItem.cpp deleted file mode 100644 index f103aaed4c..0000000000 --- a/libraries/entities-renderer/src/RenderableDebugableEntityItem.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// -// RenderableDebugableEntityItem.cpp -// libraries/entities-renderer/src/ -// -// Created by Seth Alves on 5/1/15. -// 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 "RenderableDebugableEntityItem.h" - -#include - -#include -#include -#include - - -void RenderableDebugableEntityItem::renderBoundingBox(EntityItem* entity, RenderArgs* args, - float puffedOut, glm::vec4& color) { - Q_ASSERT(args->_batch); - gpu::Batch& batch = *args->_batch; - - auto shapeTransform = entity->getTransformToCenter(); - if (puffedOut != 0.0f) { - shapeTransform.postScale(1.0f + puffedOut); - } - batch.setModelTransform(Transform()); // we want to include the scale as well - DependencyManager::get()->renderWireCubeInstance(batch, shapeTransform, color); -} - -void RenderableDebugableEntityItem::render(EntityItem* entity, RenderArgs* args) { - if (args->_debugFlags & RenderArgs::RENDER_DEBUG_SIMULATION_OWNERSHIP) { - Q_ASSERT(args->_batch); - gpu::Batch& batch = *args->_batch; - - batch.setModelTransform(entity->getTransformToCenter()); // we want to include the scale as well - - auto nodeList = DependencyManager::get(); - const QUuid& myNodeID = nodeList->getSessionUUID(); - bool highlightSimulationOwnership = (entity->getSimulatorID() == myNodeID); - if (highlightSimulationOwnership) { - glm::vec4 greenColor(0.0f, 1.0f, 0.2f, 1.0f); - renderBoundingBox(entity, args, 0.08f, greenColor); - } - - quint64 now = usecTimestampNow(); - if (now - entity->getLastEditedFromRemote() < 0.1f * USECS_PER_SECOND) { - glm::vec4 redColor(1.0f, 0.0f, 0.0f, 1.0f); - renderBoundingBox(entity, args, 0.16f, redColor); - } - - if (now - entity->getLastBroadcast() < 0.2f * USECS_PER_SECOND) { - glm::vec4 yellowColor(1.0f, 1.0f, 0.2f, 1.0f); - renderBoundingBox(entity, args, 0.24f, yellowColor); - } - - ObjectMotionState* motionState = static_cast(entity->getPhysicsInfo()); - if (motionState && motionState->isActive()) { - glm::vec4 blueColor(0.0f, 0.0f, 1.0f, 1.0f); - renderBoundingBox(entity, args, 0.32f, blueColor); - } - } -} diff --git a/libraries/entities-renderer/src/RenderableDebugableEntityItem.h b/libraries/entities-renderer/src/RenderableDebugableEntityItem.h deleted file mode 100644 index 2680d882f5..0000000000 --- a/libraries/entities-renderer/src/RenderableDebugableEntityItem.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// RenderableDebugableEntityItem.h -// libraries/entities-renderer/src/ -// -// Created by Seth Alves on 5/1/15. -// 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_RenderableDebugableEntityItem_h -#define hifi_RenderableDebugableEntityItem_h - -#include - -class RenderableDebugableEntityItem { -public: - static void renderBoundingBox(EntityItem* entity, RenderArgs* args, float puffedOut, glm::vec4& color); - static void render(EntityItem* entity, RenderArgs* args); -}; - -#endif // hifi_RenderableDebugableEntityItem_h diff --git a/libraries/entities-renderer/src/RenderableLineEntityItem.cpp b/libraries/entities-renderer/src/RenderableLineEntityItem.cpp index 3735690c33..f39c31e22b 100644 --- a/libraries/entities-renderer/src/RenderableLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLineEntityItem.cpp @@ -54,6 +54,4 @@ void RenderableLineEntityItem::render(RenderArgs* args) { DependencyManager::get()->bindSimpleProgram(batch); DependencyManager::get()->renderVertices(batch, gpu::LINE_STRIP, _lineVerticesID); } - - RenderableDebugableEntityItem::render(this, args); }; diff --git a/libraries/entities-renderer/src/RenderableLineEntityItem.h b/libraries/entities-renderer/src/RenderableLineEntityItem.h index 09f98ca364..ba990046a0 100644 --- a/libraries/entities-renderer/src/RenderableLineEntityItem.h +++ b/libraries/entities-renderer/src/RenderableLineEntityItem.h @@ -13,7 +13,6 @@ #define hifi_RenderableLineEntityItem_h #include -#include "RenderableDebugableEntityItem.h" #include "RenderableEntityItem.h" #include diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index e604bdb925..8543c00eec 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include "EntityTreeRenderer.h" #include "EntitiesRendererLogging.h" @@ -186,15 +187,28 @@ void makeEntityItemStatusGetters(RenderableModelEntityItem* entity, render::Item float normalizedDelta = delta * WAIT_THRESHOLD_INV; // Status icon will scale from 1.0f down to 0.0f after WAIT_THRESHOLD // Color is red if last update is after WAIT_THRESHOLD, green otherwise (120 deg is green) - return render::Item::Status::Value(1.0f - normalizedDelta, (normalizedDelta > 1.0f ? render::Item::Status::Value::GREEN : render::Item::Status::Value::RED)); + return render::Item::Status::Value(1.0f - normalizedDelta, (normalizedDelta > 1.0f ? + render::Item::Status::Value::GREEN : + render::Item::Status::Value::RED)); }); + statusGetters.push_back([entity] () -> render::Item::Status::Value { quint64 delta = usecTimestampNow() - entity->getLastBroadcast(); const float WAIT_THRESHOLD_INV = 1.0f / (0.4f * USECS_PER_SECOND); float normalizedDelta = delta * WAIT_THRESHOLD_INV; // Status icon will scale from 1.0f down to 0.0f after WAIT_THRESHOLD // Color is Magenta if last update is after WAIT_THRESHOLD, cyan otherwise (180 deg is green) - return render::Item::Status::Value(1.0f - normalizedDelta, (normalizedDelta > 1.0f ? render::Item::Status::Value::MAGENTA : render::Item::Status::Value::CYAN)); + return render::Item::Status::Value(1.0f - normalizedDelta, (normalizedDelta > 1.0f ? + render::Item::Status::Value::MAGENTA : + render::Item::Status::Value::CYAN)); + }); + + statusGetters.push_back([entity] () -> render::Item::Status::Value { + ObjectMotionState* motionState = static_cast(entity->getPhysicsInfo()); + if (motionState && motionState->isActive()) { + return render::Item::Status::Value(1.0f, render::Item::Status::Value::BLUE); + } + return render::Item::Status::Value(0.0f, render::Item::Status::Value::BLUE); }); } @@ -320,11 +334,12 @@ void RenderableModelEntityItem::render(RenderArgs* args) { } } } else { - glm::vec4 greenColor(0.0f, 1.0f, 0.0f, 1.0f); - RenderableDebugableEntityItem::renderBoundingBox(this, args, 0.0f, greenColor); + static glm::vec4 greenColor(0.0f, 1.0f, 0.0f, 1.0f); + gpu::Batch& batch = *args->_batch; + auto shapeTransform = getTransformToCenter(); + batch.setModelTransform(Transform()); // we want to include the scale as well + DependencyManager::get()->renderWireCubeInstance(batch, shapeTransform, greenColor); } - - RenderableDebugableEntityItem::render(this, args); } Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 4dc1cced48..04a1694dd3 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -16,7 +16,6 @@ #include #include -#include "RenderableDebugableEntityItem.h" class Model; class EntityTreeRenderer; diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 7bec8f2b03..32418199b8 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -153,6 +153,4 @@ void RenderablePolyLineEntityItem::render(RenderArgs* args) { batch.setInputBuffer(0, _verticesBuffer, 0, _format->getChannels().at(0)._stride); batch.draw(gpu::TRIANGLE_STRIP, _numVertices, 0); - - RenderableDebugableEntityItem::render(this, args); }; diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h index 2832053639..c8a47cce0c 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h @@ -14,7 +14,6 @@ #include #include -#include "RenderableDebugableEntityItem.h" #include "RenderableEntityItem.h" #include #include diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index fd5a9a6b4a..cd88638e51 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -538,8 +538,6 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) { batch._glUniform3f(voxelVolumeSizeLocation, _voxelVolumeSize.x, _voxelVolumeSize.y, _voxelVolumeSize.z); batch.drawIndexed(gpu::TRIANGLES, mesh->getNumIndices(), 0); - - RenderableDebugableEntityItem::render(this, args); } bool RenderablePolyVoxEntityItem::addToScene(EntityItemPointer self, diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index ef44ba5ab0..9d0931a47e 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -21,7 +21,6 @@ #include #include "PolyVoxEntityItem.h" -#include "RenderableDebugableEntityItem.h" #include "RenderableEntityItem.h" #include "gpu/Context.h" diff --git a/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp b/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp index 246cd2fea7..0400ecb999 100644 --- a/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp @@ -20,7 +20,6 @@ #include #include -#include "RenderableDebugableEntityItem.h" #include "../render-utils/simple_vert.h" #include "../render-utils/simple_frag.h" @@ -70,7 +69,4 @@ void RenderableSphereEntityItem::render(RenderArgs* args) { batch.setModelTransform(Transform()); DependencyManager::get()->renderSolidSphereInstance(batch, modelTransform, sphereColor); } - - - RenderableDebugableEntityItem::render(this, args); }; From f3d26e163ddbb87e27e933b34b864962569d97f5 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sat, 7 Nov 2015 07:19:27 -0800 Subject: [PATCH 02/61] turn _drawItemStatus into a bitfield, split out bounding boxes and network/physics-sim-ownership. hook Display-Simulation-Ownership menu item to this system --- examples/utilities/tools/renderEngineDebug.js | 22 ++++++++++++++---- interface/src/Application.cpp | 7 +++--- .../render-utils/src/RenderDeferredTask.h | 7 +++++- libraries/render/src/render/DrawStatus.cpp | 23 +++++++++++-------- libraries/render/src/render/Engine.h | 6 ++++- .../src/SceneScriptingInterface.h | 6 ++--- 6 files changed, 49 insertions(+), 22 deletions(-) diff --git a/examples/utilities/tools/renderEngineDebug.js b/examples/utilities/tools/renderEngineDebug.js index 3271741985..cca97b7184 100755 --- a/examples/utilities/tools/renderEngineDebug.js +++ b/examples/utilities/tools/renderEngineDebug.js @@ -62,10 +62,24 @@ var overlaysCounter = new CounterWidget(panel, "Overlays", ); -panel.newCheckbox("Display status", - function(value) { Scene.setEngineDisplayItemStatus(value); }, - function() { return Scene.doEngineDisplayItemStatus(); }, - function(value) { return (value); } +// see libraries/render/src/render/Engine.h +var showDisplayStatusFlag = 1; +var showNetworkStatusFlag = 2; + +panel.newCheckbox("Display status", + function(value) { Scene.setEngineDisplayItemStatus(value ? + Scene.doEngineDisplayItemStatus() | showDisplayStatusFlag : + Scene.doEngineDisplayItemStatus() & ~showDisplayStatusFlag); }, + function() { return (Scene.doEngineDisplayItemStatus() & showDisplayStatusFlag) > 0; }, + function(value) { return (value & showDisplayStatusFlag) > 0; } +); + +panel.newCheckbox("Network/Physics status", + function(value) { Scene.setEngineDisplayItemStatus(value ? + Scene.doEngineDisplayItemStatus() | showNetworkStatusFlag : + Scene.doEngineDisplayItemStatus() & ~showNetworkStatusFlag); }, + function() { return (Scene.doEngineDisplayItemStatus() & showNetworkStatusFlag) > 0; }, + function(value) { return (value & showNetworkStatusFlag) > 0; } ); var tickTackPeriod = 500; diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 718d06c6e5..5a3d66be55 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3493,10 +3493,6 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se if (Menu::getInstance()->isOptionChecked(MenuOption::PhysicsShowHulls)) { renderDebugFlags = (RenderArgs::DebugFlags) (renderDebugFlags | (int)RenderArgs::RENDER_DEBUG_HULLS); } - if (Menu::getInstance()->isOptionChecked(MenuOption::PhysicsShowOwned)) { - renderDebugFlags = - (RenderArgs::DebugFlags) (renderDebugFlags | (int)RenderArgs::RENDER_DEBUG_SIMULATION_OWNERSHIP); - } renderArgs->_debugFlags = renderDebugFlags; //ViveControllerManager::getInstance().updateRendering(renderArgs, _main3DScene, pendingChanges); } @@ -3556,6 +3552,9 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se renderContext._maxDrawnOverlay3DItems = sceneInterface->getEngineMaxDrawnOverlay3DItems(); renderContext._drawItemStatus = sceneInterface->doEngineDisplayItemStatus(); + if (Menu::getInstance()->isOptionChecked(MenuOption::PhysicsShowOwned)) { + renderContext._drawItemStatus |= render::showNetworkStatusFlag; + } renderContext._drawHitEffect = sceneInterface->doEngineDisplayHitEffect(); renderContext._occlusionStatus = Menu::getInstance()->isOptionChecked(MenuOption::DebugAmbientOcclusion); diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 04483fc037..6daa90b1ed 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -97,7 +97,12 @@ public: int _drawStatusJobIndex = -1; int _drawHitEffectJobIndex = -1; - void setDrawItemStatus(bool draw) { if (_drawStatusJobIndex >= 0) { _jobs[_drawStatusJobIndex].setEnabled(draw); } } + void setDrawItemStatus(int draw) { + if (_drawStatusJobIndex >= 0) { + _jobs[_drawStatusJobIndex].setEnabled(draw > 0); + } + } + bool doDrawItemStatus() const { if (_drawStatusJobIndex >= 0) { return _jobs[_drawStatusJobIndex].isEnabled(); } else { return false; } } void setDrawHitEffect(bool draw) { if (_drawHitEffectJobIndex >= 0) { _jobs[_drawHitEffectJobIndex].setEnabled(draw); } } diff --git a/libraries/render/src/render/DrawStatus.cpp b/libraries/render/src/render/DrawStatus.cpp index 57e21a1511..921098df06 100644 --- a/libraries/render/src/render/DrawStatus.cpp +++ b/libraries/render/src/render/DrawStatus.cpp @@ -144,20 +144,25 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex const unsigned int VEC3_ADRESS_OFFSET = 3; - for (int i = 0; i < nbItems; i++) { - batch._glUniform3fv(_drawItemBoundPosLoc, 1, (const float*) (itemAABox + i)); - batch._glUniform3fv(_drawItemBoundDimLoc, 1, ((const float*) (itemAABox + i)) + VEC3_ADRESS_OFFSET); + if ((renderContext->_drawItemStatus & showDisplayStatusFlag) > 0) { + for (int i = 0; i < nbItems; i++) { + batch._glUniform3fv(_drawItemBoundPosLoc, 1, (const float*) (itemAABox + i)); + batch._glUniform3fv(_drawItemBoundDimLoc, 1, ((const float*) (itemAABox + i)) + VEC3_ADRESS_OFFSET); - batch.draw(gpu::LINES, 24, 0); + batch.draw(gpu::LINES, 24, 0); + } } batch.setPipeline(getDrawItemStatusPipeline()); - for (int i = 0; i < nbItems; i++) { - batch._glUniform3fv(_drawItemStatusPosLoc, 1, (const float*) (itemAABox + i)); - batch._glUniform3fv(_drawItemStatusDimLoc, 1, ((const float*) (itemAABox + i)) + VEC3_ADRESS_OFFSET); - batch._glUniform4iv(_drawItemStatusValueLoc, 1, (const int*) (itemStatus + i)); - batch.draw(gpu::TRIANGLES, 24, 0); + if ((renderContext->_drawItemStatus & showNetworkStatusFlag) > 0) { + for (int i = 0; i < nbItems; i++) { + batch._glUniform3fv(_drawItemStatusPosLoc, 1, (const float*) (itemAABox + i)); + batch._glUniform3fv(_drawItemStatusDimLoc, 1, ((const float*) (itemAABox + i)) + VEC3_ADRESS_OFFSET); + batch._glUniform4iv(_drawItemStatusValueLoc, 1, (const int*) (itemStatus + i)); + + batch.draw(gpu::TRIANGLES, 24, 0); + } } }); } diff --git a/libraries/render/src/render/Engine.h b/libraries/render/src/render/Engine.h index 5da7956b22..7c11246cff 100644 --- a/libraries/render/src/render/Engine.h +++ b/libraries/render/src/render/Engine.h @@ -25,6 +25,10 @@ public: }; typedef std::shared_ptr SceneContextPointer; +// see examples/utilities/tools/renderEngineDebug.js +const int showDisplayStatusFlag = 1; +const int showNetworkStatusFlag = 2; + class RenderContext { public: @@ -49,7 +53,7 @@ public: int _numDrawnOverlay3DItems = 0; int _maxDrawnOverlay3DItems = -1; - bool _drawItemStatus = false; + int _drawItemStatus = 0; bool _drawHitEffect = false; bool _occlusionStatus = false; diff --git a/libraries/script-engine/src/SceneScriptingInterface.h b/libraries/script-engine/src/SceneScriptingInterface.h index 95919d6c0c..6be0ce44a8 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.h +++ b/libraries/script-engine/src/SceneScriptingInterface.h @@ -107,8 +107,8 @@ public: Q_INVOKABLE void setEngineMaxDrawnOverlay3DItems(int count) { _maxDrawnOverlay3DItems = count; } Q_INVOKABLE int getEngineMaxDrawnOverlay3DItems() { return _maxDrawnOverlay3DItems; } - Q_INVOKABLE void setEngineDisplayItemStatus(bool display) { _drawItemStatus = display; } - Q_INVOKABLE bool doEngineDisplayItemStatus() { return _drawItemStatus; } + Q_INVOKABLE void setEngineDisplayItemStatus(int display) { _drawItemStatus = display; } + Q_INVOKABLE int doEngineDisplayItemStatus() { return _drawItemStatus; } Q_INVOKABLE void setEngineDisplayHitEffect(bool display) { _drawHitEffect = display; } Q_INVOKABLE bool doEngineDisplayHitEffect() { return _drawHitEffect; } @@ -143,7 +143,7 @@ protected: int _maxDrawnTransparentItems = -1; int _maxDrawnOverlay3DItems = -1; - bool _drawItemStatus = false; + int _drawItemStatus = 0; bool _drawHitEffect = false; From d535109cafbc5b6cfe925a0303c4c18b275a083c Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 10 Nov 2015 09:49:31 -0800 Subject: [PATCH 03/61] attempt to fix render-collision hull feature --- .../src/RenderableModelEntityItem.cpp | 10 ++++---- .../src/RenderableModelEntityItem.h | 2 ++ .../src/RenderableZoneEntityItem.cpp | 2 +- libraries/render-utils/src/Model.cpp | 24 ++++++++++++++----- libraries/render-utils/src/Model.h | 8 +++++-- libraries/shared/src/RenderArgs.h | 7 +++--- 6 files changed, 36 insertions(+), 17 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 8543c00eec..d33e52fa6b 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -227,7 +227,7 @@ bool RenderableModelEntityItem::addToScene(EntityItemPointer self, std::shared_p // note: we don't care if the model fails to add items, we always added our meta item and therefore we return // true so that the system knows our meta item is in the scene! - _model->addToScene(scene, pendingChanges, statusGetters); + _model->addToScene(scene, pendingChanges, statusGetters, _showCollisionHull); } return true; @@ -259,14 +259,16 @@ void RenderableModelEntityItem::render(RenderArgs* args) { // check to see if when we added our models to the scene they were ready, if they were not ready, then // fix them up in the scene - if (_model->needsFixupInScene()) { + bool shouldShowCollisionHull = (args->_debugFlags & (int)RenderArgs::RENDER_DEBUG_HULLS) > 0; + if (_model->needsFixupInScene() || _showCollisionHull != shouldShowCollisionHull) { + _showCollisionHull = shouldShowCollisionHull; render::PendingChanges pendingChanges; _model->removeFromScene(scene, pendingChanges); render::Item::Status::Getters statusGetters; makeEntityItemStatusGetters(this, statusGetters); - _model->addToScene(scene, pendingChanges, statusGetters); + _model->addToScene(scene, pendingChanges, statusGetters, _showCollisionHull); scene->enqueuePendingChanges(pendingChanges); } @@ -288,7 +290,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { EntityTreeRenderer* renderer = static_cast(args->_renderer); getModel(renderer); } - + if (_model) { // handle animations.. if (hasAnimation()) { diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 04a1694dd3..c4e36c240a 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -81,6 +81,8 @@ private: bool _dimensionsInitialized = true; render::ItemID _myMetaItem; + + bool _showCollisionHull = false; }; #endif // hifi_RenderableModelEntityItem_h diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index ff56bef46b..62d98f3322 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -112,7 +112,7 @@ void RenderableZoneEntityItem::render(RenderArgs* args) { render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); render::PendingChanges pendingChanges; _model->removeFromScene(scene, pendingChanges); - _model->addToScene(scene, pendingChanges); + _model->addToScene(scene, pendingChanges, false); scene->enqueuePendingChanges(pendingChanges); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 6aae7ad1cb..92f057647c 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -508,8 +508,10 @@ void Model::setVisibleInScene(bool newValue, std::shared_ptr scen } -bool Model::addToScene(std::shared_ptr scene, render::PendingChanges& pendingChanges) { - if (!_meshGroupsKnown && isLoaded()) { +bool Model::addToScene(std::shared_ptr scene, render::PendingChanges& pendingChanges, bool showCollisionHull) { + + if ((!_meshGroupsKnown || showCollisionHull != _showCollisionHull) && isLoaded()) { + _showCollisionHull = showCollisionHull; segregateMeshGroups(); } @@ -532,8 +534,12 @@ bool Model::addToScene(std::shared_ptr scene, render::PendingChan return somethingAdded; } -bool Model::addToScene(std::shared_ptr scene, render::PendingChanges& pendingChanges, render::Item::Status::Getters& statusGetters) { - if (!_meshGroupsKnown && isLoaded()) { +bool Model::addToScene(std::shared_ptr scene, + render::PendingChanges& pendingChanges, + render::Item::Status::Getters& statusGetters, + bool showCollisionHull) { + if ((!_meshGroupsKnown || showCollisionHull != _showCollisionHull) && isLoaded()) { + _showCollisionHull = showCollisionHull; segregateMeshGroups(); } @@ -1144,8 +1150,14 @@ AABox Model::getPartBounds(int meshIndex, int partIndex) { } void Model::segregateMeshGroups() { - const FBXGeometry& geometry = _geometry->getFBXGeometry(); - const std::vector>& networkMeshes = _geometry->getMeshes(); + QSharedPointer networkGeometry; + if (_showCollisionHull && _collisionGeometry && _collisionGeometry->isLoaded()) { + networkGeometry = _collisionGeometry; + } else { + networkGeometry = _geometry; + } + const FBXGeometry& geometry = networkGeometry->getFBXGeometry(); + const std::vector>& networkMeshes = networkGeometry->getMeshes(); _rig->makeAnimSkeleton(geometry); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index f5d5f40363..b154ae2b52 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -76,10 +76,13 @@ public: return !_needsReload && isRenderable() && isActive() && isLoaded(); } bool initWhenReady(render::ScenePointer scene); - bool addToScene(std::shared_ptr scene, render::PendingChanges& pendingChanges); bool addToScene(std::shared_ptr scene, render::PendingChanges& pendingChanges, - render::Item::Status::Getters& statusGetters); + bool showCollisionHull = false); + bool addToScene(std::shared_ptr scene, + render::PendingChanges& pendingChanges, + render::Item::Status::Getters& statusGetters, + bool showCollisionHull = false); void removeFromScene(std::shared_ptr scene, render::PendingChanges& pendingChanges); void renderSetup(RenderArgs* args); bool isRenderable() const { return !_meshStates.isEmpty() || (isActive() && _geometry->getMeshes().empty()); } @@ -368,6 +371,7 @@ private: bool _readyWhenAdded = false; bool _needsReload = true; bool _needsUpdateClusterMatrices = true; + bool _showCollisionHull = false; friend class MeshPartPayload; protected: diff --git a/libraries/shared/src/RenderArgs.h b/libraries/shared/src/RenderArgs.h index 25eed96490..fcacf7aaed 100644 --- a/libraries/shared/src/RenderArgs.h +++ b/libraries/shared/src/RenderArgs.h @@ -68,17 +68,16 @@ public: class RenderArgs { public: typedef std::function ShoudRenderFunctor; - + enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE, MIRROR_RENDER_MODE }; enum RenderSide { MONO, STEREO_LEFT, STEREO_RIGHT }; enum DebugFlags { RENDER_DEBUG_NONE = 0, - RENDER_DEBUG_HULLS = 1, - RENDER_DEBUG_SIMULATION_OWNERSHIP = 2, + RENDER_DEBUG_HULLS = 1 }; - + RenderArgs(std::shared_ptr context = nullptr, OctreeRenderer* renderer = nullptr, ViewFrustum* viewFrustum = nullptr, From 8e466190e0f69c122f1bb73d8d8a9282b500a8c6 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 10 Nov 2015 10:15:58 -0800 Subject: [PATCH 04/61] working toward display icons for debug/status display --- .../render-utils/src/RenderDeferredTask.cpp | 9 +++++++-- libraries/render/src/render/DrawStatus.cpp | 16 ++++++++++++++-- libraries/render/src/render/DrawStatus.h | 11 +++++++++-- libraries/render/src/render/DrawTask.h | 2 +- libraries/render/src/render/Scene.cpp | 5 ++++- libraries/render/src/render/Scene.h | 8 ++++++-- libraries/render/src/render/drawItemStatus.slf | 9 ++++++++- libraries/render/src/render/drawItemStatus.slv | 12 +++++++----- 8 files changed, 56 insertions(+), 16 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 845c96372c..baa4b8f259 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -12,6 +12,7 @@ #include "RenderDeferredTask.h" #include +#include #include #include #include @@ -111,7 +112,11 @@ RenderDeferredTask::RenderDeferredTask() : Task() { _jobs.push_back(Job(new DepthSortItems::JobModel("DepthSortTransparent", _jobs.back().getOutput(), DepthSortItems(false)))); _jobs.push_back(Job(new DrawTransparentDeferred::JobModel("TransparentDeferred", _jobs.back().getOutput()))); - _jobs.push_back(Job(new render::DrawStatus::JobModel("DrawStatus", renderedOpaques))); + // Grab a texture map representing the different status icons and assign that to the drawStatsuJob + auto iconMapPath = PathUtils::resourcesPath() + "images/hifi-logo.svg"; + + auto statusIconMap = DependencyManager::get()->getImageTexture(iconMapPath); + _jobs.push_back(Job(new render::DrawStatus::JobModel("DrawStatus", renderedOpaques, DrawStatus(statusIconMap)))); _jobs.back().setEnabled(false); @@ -387,4 +392,4 @@ void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const }); args->_batch = nullptr; -} \ No newline at end of file +} diff --git a/libraries/render/src/render/DrawStatus.cpp b/libraries/render/src/render/DrawStatus.cpp index 57e21a1511..190370fd48 100644 --- a/libraries/render/src/render/DrawStatus.cpp +++ b/libraries/render/src/render/DrawStatus.cpp @@ -29,7 +29,7 @@ using namespace render; -const gpu::PipelinePointer& DrawStatus::getDrawItemBoundsPipeline() { +const gpu::PipelinePointer DrawStatus::getDrawItemBoundsPipeline() { if (!_drawItemBoundsPipeline) { auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(drawItemBounds_vert))); auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(drawItemBounds_frag))); @@ -56,13 +56,14 @@ const gpu::PipelinePointer& DrawStatus::getDrawItemBoundsPipeline() { return _drawItemBoundsPipeline; } -const gpu::PipelinePointer& DrawStatus::getDrawItemStatusPipeline() { +const gpu::PipelinePointer DrawStatus::getDrawItemStatusPipeline() { if (!_drawItemStatusPipeline) { auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(drawItemStatus_vert))); auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(drawItemStatus_frag))); gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("iconStatusMap"), 0)); gpu::Shader::makeProgram(*program, slotBindings); _drawItemStatusPosLoc = program->getUniforms().findLocation("inBoundPos"); @@ -84,6 +85,14 @@ const gpu::PipelinePointer& DrawStatus::getDrawItemStatusPipeline() { return _drawItemStatusPipeline; } +void DrawStatus::setStatusIconMap(const gpu::TexturePointer& map) { + _statusIconMap = map; +} + +const gpu::TexturePointer DrawStatus::getStatusIconMap() const { + return _statusIconMap; +} + void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems) { assert(renderContext->args); assert(renderContext->args->_viewFrustum); @@ -151,6 +160,8 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex batch.draw(gpu::LINES, 24, 0); } + batch.setResourceTexture(0, gpu::TextureView(getStatusIconMap(), 0)); + batch.setPipeline(getDrawItemStatusPipeline()); for (int i = 0; i < nbItems; i++) { batch._glUniform3fv(_drawItemStatusPosLoc, 1, (const float*) (itemAABox + i)); @@ -159,5 +170,6 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex batch.draw(gpu::TRIANGLES, 24, 0); } + batch.setResourceTexture(0, 0); }); } diff --git a/libraries/render/src/render/DrawStatus.h b/libraries/render/src/render/DrawStatus.h index a96b897f5c..bb9cb07e4b 100644 --- a/libraries/render/src/render/DrawStatus.h +++ b/libraries/render/src/render/DrawStatus.h @@ -28,15 +28,22 @@ namespace render { gpu::PipelinePointer _drawItemStatusPipeline; gpu::BufferPointer _itemBounds; gpu::BufferPointer _itemStatus; + gpu::TexturePointer _statusIconMap; public: + DrawStatus() {} + DrawStatus(const gpu::TexturePointer statusIconMap) { setStatusIconMap(statusIconMap); } + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems); typedef Job::ModelI JobModel; - const gpu::PipelinePointer& getDrawItemBoundsPipeline(); - const gpu::PipelinePointer& getDrawItemStatusPipeline(); + const gpu::PipelinePointer getDrawItemBoundsPipeline(); + const gpu::PipelinePointer getDrawItemStatusPipeline(); + + void setStatusIconMap(const gpu::TexturePointer& map); + const gpu::TexturePointer getStatusIconMap() const; }; } diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index ed51273f88..3f628c3a02 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -143,7 +143,7 @@ public: const Varying getInput() const { return _input; } - ModelI(const std::string& name, const Varying& input): Concept(name), _input(input) {} + ModelI(const std::string& name, const Varying& input, Data data = Data()) : Concept(name), _data(data), _input(input) {} ModelI(const std::string& name, Data data): Concept(name), _data(data) {} void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index fb6782e011..2081d5267f 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -72,7 +72,10 @@ void Item::Status::Value::setScale(float scale) { void Item::Status::Value::setColor(float hue) { // Convert the HUe from range [0, 360] to signed normalized value const float HUE_MAX = 360.0f; - _color = (std::numeric_limits::max() - 1) * 0.5f * (1.0f + std::max(std::min(hue, HUE_MAX), 0.0f) / HUE_MAX); + _color = (std::numeric_limits::max()) * (std::max(std::min(hue, HUE_MAX), 0.0f) / HUE_MAX); +} +void Item::Status::Value::setIcon(unsigned char icon) { + _icon = icon; } void Item::Status::getPackedValues(glm::ivec4& values) const { diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index ab71a583b4..459f15055f 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -206,17 +206,21 @@ public: // It can be scaled in the range [0, 1] and the color hue in the range [0, 360] representing the color wheel hue class Value { unsigned short _scale = 0xFFFF; - unsigned short _color = 0xFFFF; + unsigned char _color = 0xFF; + unsigned char _icon = 0xFF; public: const static Value INVALID; // Invalid value meanss the status won't show Value() {} - Value(float scale, float hue) { setScale(scale); setColor(hue); } + Value(float scale, float hue, unsigned char icon = 0) { setScale(scale); setColor(hue); setIcon(icon); } // It can be scaled in the range [0, 1] void setScale(float scale); // the color hue in the range [0, 360] representing the color wheel hue void setColor(float hue); + // the icon to display in the range [0, 255], where 0 means no icon, just filled quad and anything else would + // hopefully have an icon available to display (see DrawStatusJob) + void setIcon(unsigned char icon); // Standard color Hue static const float RED; // 0.0f; diff --git a/libraries/render/src/render/drawItemStatus.slf b/libraries/render/src/render/drawItemStatus.slf index 4cc45db2ec..3b902e151d 100644 --- a/libraries/render/src/render/drawItemStatus.slf +++ b/libraries/render/src/render/drawItemStatus.slf @@ -12,9 +12,16 @@ // in vec4 varColor; +in vec3 varTexcoord; out vec4 outFragColor; +uniform sampler2D _icons; + void main(void) { - outFragColor = varColor; + if (varTexcoord.z > 0.0f) { + outFragColor = texture(_icons, varTexcoord.xy) * varColor; + } else { + outFragColor = varColor; + } } diff --git a/libraries/render/src/render/drawItemStatus.slv b/libraries/render/src/render/drawItemStatus.slv index 178293575d..8a9ca591c7 100644 --- a/libraries/render/src/render/drawItemStatus.slv +++ b/libraries/render/src/render/drawItemStatus.slv @@ -17,6 +17,7 @@ <$declareStandardTransform()$> out vec4 varColor; +out vec3 varTexcoord; uniform vec3 inBoundPos; uniform vec3 inBoundDim; @@ -43,9 +44,10 @@ vec3 paintRainbow(float normalizedHue) { } } -vec2 unpackStatus(int v) { - return vec2(clamp(float(int((v >> 0) & 0xFFFF) - 32727) / 32727.0, -1.0, 1.0), - clamp(float(int((v >> 16) & 0xFFFF) - 32727) / 32727.0, -1.0, 1.0)); +vec3 unpackStatus(int v) { + return vec3(clamp(float(int((v >> 0) & 0xFFFF) - 32727) / 32727.0, -1.0, 1.0), + clamp(float(uint((v >> 16) & 0xFF)) / 255.0, 0.0, 1.0), + clamp(float(int((v >> 24) & 0xFF)), 0.0, 256.0)); } void main(void) { @@ -78,14 +80,14 @@ void main(void) { } // unpack to get x and y satus - vec2 iconStatus = unpackStatus(inStatus[iconNum]); + vec3 iconStatus = unpackStatus(inStatus[iconNum]); // Use the status for showing a color varColor = vec4(paintRainbow(abs(iconStatus.y)), 1.0); // Also changes the size of the notification vec2 iconScale = ICON_PIXEL_SIZE; - iconScale = max(vec2(1, 1), (iconScale * iconStatus.x)); + iconScale = max(vec2(0, 0), (iconScale * iconStatus.x)); //Offset icon to the right based on the iconNum vec2 offset = vec2(iconNum * (ICON_PIXEL_SIZE.x + MARGIN_PIXEL_SIZE.x), 0); From 5e4f30b2bb8d073238093cdaca2aaff23b7398ef Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 10 Nov 2015 13:58:09 -0800 Subject: [PATCH 05/61] improve terse entity logging. change how action data sending is triggered --- .../src/octree/OctreeSendThread.cpp | 7 +- libraries/entities/src/EntityItem.cpp | 1 + .../entities/src/EntityScriptingInterface.cpp | 15 ++-- libraries/entities/src/EntityTree.cpp | 78 ++++++++++++++++++- 4 files changed, 91 insertions(+), 10 deletions(-) diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 2696c92253..4e01d1562b 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -17,6 +17,7 @@ #include "OctreeSendThread.h" #include "OctreeServer.h" #include "OctreeServerConsts.h" +#include "OctreeLogging.h" quint64 startSceneSleepTime = 0; quint64 endSceneSleepTime = 0; @@ -571,9 +572,9 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus if (somethingToSend) { - qDebug() << "Hit PPS Limit, packetsSentThisInterval =" << packetsSentThisInterval - << " maxPacketsPerInterval = " << maxPacketsPerInterval - << " clientMaxPacketsPerInterval = " << clientMaxPacketsPerInterval; + qCDebug(octree) << "Hit PPS Limit, packetsSentThisInterval =" << packetsSentThisInterval + << " maxPacketsPerInterval = " << maxPacketsPerInterval + << " clientMaxPacketsPerInterval = " << clientMaxPacketsPerInterval; } diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index cce3045049..dbea43d514 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1770,6 +1770,7 @@ void EntityItem::serializeActions(bool& success, QByteArray& result) const { serializedActionsStream << serializedActions; if (result.size() >= _maxActionsDataSize) { + qDebug() << "EntityItem::serializeActions size is too large -- " << result.size() << ">=" << _maxActionsDataSize; success = false; return; } diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 8ca0e9b5fa..e5caab3a71 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -611,7 +611,8 @@ QUuid EntityScriptingInterface::addAction(const QString& actionTypeString, const QVariantMap& arguments) { QUuid actionID = QUuid::createUuid(); auto actionFactory = DependencyManager::get(); - bool success = actionWorker(entityID, [&](EntitySimulation* simulation, EntityItemPointer entity) { + bool success = true; + actionWorker(entityID, [&](EntitySimulation* simulation, EntityItemPointer entity) { // create this action even if the entity doesn't have physics info. it will often be the // case that a script adds an action immediately after an object is created, and the physicsInfo // is computed asynchronously. @@ -620,17 +621,18 @@ QUuid EntityScriptingInterface::addAction(const QString& actionTypeString, // } EntityActionType actionType = EntityActionInterface::actionTypeFromString(actionTypeString); if (actionType == ACTION_TYPE_NONE) { + success = false; return false; } EntityActionPointer action = actionFactory->factory(actionType, actionID, entity, arguments); if (action) { - entity->addAction(simulation, action); + success = entity->addAction(simulation, action); auto nodeList = DependencyManager::get(); const QUuid myNodeID = nodeList->getSessionUUID(); if (entity->getSimulatorID() != myNodeID) { entity->flagForOwnership(); } - return true; + return false; // Physics will cause a packet to be sent, so don't send from here. } return false; }); @@ -656,9 +658,12 @@ bool EntityScriptingInterface::updateAction(const QUuid& entityID, const QUuid& } bool EntityScriptingInterface::deleteAction(const QUuid& entityID, const QUuid& actionID) { - return actionWorker(entityID, [&](EntitySimulation* simulation, EntityItemPointer entity) { - return entity->removeAction(simulation, actionID); + bool success = false; + actionWorker(entityID, [&](EntitySimulation* simulation, EntityItemPointer entity) { + success = entity->removeAction(simulation, actionID); + return false; // Physics will cause a packet to be sent, so don't send from here. }); + return success; } QVector EntityScriptingInterface::getActionIDs(const QUuid& entityID) { diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 8e32158362..f1a85a1b6d 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -612,6 +612,14 @@ EntityItemPointer EntityTree::findEntityByEntityItemID(const EntityItemID& entit } void EntityTree::fixupTerseEditLogging(EntityItemProperties& properties, QList& changedProperties) { + static quint64 lastTerseLog = 0; + quint64 now = usecTimestampNow(); + + if (now - lastTerseLog > USECS_PER_SECOND) { + qCDebug(entities) << "-------------------------"; + } + lastTerseLog = now; + if (properties.simulationOwnerChanged()) { int simIndex = changedProperties.indexOf("simulationOwner"); if (simIndex >= 0) { @@ -619,6 +627,70 @@ void EntityTree::fixupTerseEditLogging(EntityItemProperties& properties, QList= 0) { + glm::vec3 value = properties.getVelocity(); + QString changeHint = "0"; + if (value.x + value.y + value.z > 0) { + changeHint = "+"; + } else if (value.x + value.y + value.z < 0) { + changeHint = "-"; + } + changedProperties[index] = QString("velocity:") + changeHint; + } + } + + if (properties.gravityChanged()) { + int index = changedProperties.indexOf("gravity"); + if (index >= 0) { + glm::vec3 value = properties.getGravity(); + QString changeHint = "0"; + if (value.x + value.y + value.z > 0) { + changeHint = "+"; + } else if (value.x + value.y + value.z < 0) { + changeHint = "-"; + } + changedProperties[index] = QString("gravity:") + changeHint; + } + } + + if (properties.actionDataChanged()) { + int index = changedProperties.indexOf("actionData"); + if (index >= 0) { + QByteArray value = properties.getActionData(); + QString changeHint = "0"; + if (value.size() > 0) { + changeHint = "+"; + } + changedProperties[index] = QString("actionData:") + changeHint; + } + } + + if (properties.ignoreForCollisionsChanged()) { + int index = changedProperties.indexOf("ignoreForCollisions"); + if (index >= 0) { + bool value = properties.getIgnoreForCollisions(); + QString changeHint = "0"; + if (value) { + changeHint = "1"; + } + changedProperties[index] = QString("ignoreForCollisions:") + changeHint; + } + } + + if (properties.collisionsWillMoveChanged()) { + int index = changedProperties.indexOf("collisionsWillMove"); + if (index >= 0) { + bool value = properties.getCollisionsWillMove(); + QString changeHint = "0"; + if (value) { + changeHint = "1"; + } + changedProperties[index] = QString("collisionsWillMove:") + changeHint; + } + } } int EntityTree::processEditPacketData(NLPacket& packet, const unsigned char* editData, int maxLength, @@ -673,7 +745,9 @@ int EntityTree::processEditPacketData(NLPacket& packet, const unsigned char* edi if (wantTerseEditLogging()) { QList changedProperties = properties.listChangedProperties(); fixupTerseEditLogging(properties, changedProperties); - qCDebug(entities) << "edit" << entityItemID.toString() << changedProperties; + QString itemName = + existingEntity->getName() != "" ? existingEntity->getName() : entityItemID.toString(); + qCDebug(entities) << "edit" << itemName << changedProperties; } endLogging = usecTimestampNow(); @@ -703,7 +777,7 @@ int EntityTree::processEditPacketData(NLPacket& packet, const unsigned char* edi if (wantTerseEditLogging()) { QList changedProperties = properties.listChangedProperties(); fixupTerseEditLogging(properties, changedProperties); - qCDebug(entities) << "add" << entityItemID.toString() << changedProperties; + qCDebug(entities) << "add" << entityItemID << changedProperties; } endLogging = usecTimestampNow(); From 82bd5060860a2cb4ab25f7c8b10bb7422434b08f Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 10 Nov 2015 14:32:57 -0800 Subject: [PATCH 06/61] adjust how EntityMotionState updates its idea of what the server knows about an entity --- .../entities/src/EntityScriptingInterface.cpp | 21 +++++++++---------- libraries/physics/src/EntityMotionState.cpp | 5 +++++ 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index e5caab3a71..bc57f2c72c 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -611,7 +611,7 @@ QUuid EntityScriptingInterface::addAction(const QString& actionTypeString, const QVariantMap& arguments) { QUuid actionID = QUuid::createUuid(); auto actionFactory = DependencyManager::get(); - bool success = true; + bool success = false; actionWorker(entityID, [&](EntitySimulation* simulation, EntityItemPointer entity) { // create this action even if the entity doesn't have physics info. it will often be the // case that a script adds an action immediately after an object is created, and the physicsInfo @@ -621,20 +621,19 @@ QUuid EntityScriptingInterface::addAction(const QString& actionTypeString, // } EntityActionType actionType = EntityActionInterface::actionTypeFromString(actionTypeString); if (actionType == ACTION_TYPE_NONE) { - success = false; return false; } EntityActionPointer action = actionFactory->factory(actionType, actionID, entity, arguments); - if (action) { - success = entity->addAction(simulation, action); - auto nodeList = DependencyManager::get(); - const QUuid myNodeID = nodeList->getSessionUUID(); - if (entity->getSimulatorID() != myNodeID) { - entity->flagForOwnership(); - } - return false; // Physics will cause a packet to be sent, so don't send from here. + if (!action) { + return false; } - return false; + success = entity->addAction(simulation, action); + auto nodeList = DependencyManager::get(); + const QUuid myNodeID = nodeList->getSessionUUID(); + if (entity->getSimulatorID() != myNodeID) { + entity->flagForOwnership(); + } + return false; // Physics will cause a packet to be sent, so don't send from here. }); if (success) { return actionID; diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index c8a0f87b6d..2a7bde2377 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -86,6 +86,11 @@ void EntityMotionState::updateServerPhysicsVariables(const QUuid& sessionID) { return; } + if (_entity->shouldSuppressLocationEdits()) { + // if we send now, the changes will be ignored, so don't update our idea of what the server knows. + return; + } + _serverPosition = _entity->getPosition(); _serverRotation = _entity->getRotation(); _serverVelocity = _entity->getVelocity(); From e067195dfe3585c99c7ed299d111c08ba637a6bb Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 10 Nov 2015 14:42:40 -0800 Subject: [PATCH 07/61] adjust how EntityMotionState updates its idea of what the server knows about an entity --- libraries/physics/src/EntityMotionState.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 2a7bde2377..e61523587e 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -86,6 +86,8 @@ void EntityMotionState::updateServerPhysicsVariables(const QUuid& sessionID) { return; } + _serverActionData = _entity->getActionData(); + if (_entity->shouldSuppressLocationEdits()) { // if we send now, the changes will be ignored, so don't update our idea of what the server knows. return; @@ -96,7 +98,6 @@ void EntityMotionState::updateServerPhysicsVariables(const QUuid& sessionID) { _serverVelocity = _entity->getVelocity(); _serverAngularVelocity = _entity->getAngularVelocity(); _serverAcceleration = _entity->getAcceleration(); - _serverActionData = _entity->getActionData(); } // virtual @@ -446,11 +447,13 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, const Q } // remember properties for local server prediction - _serverPosition = _entity->getPosition(); - _serverRotation = _entity->getRotation(); - _serverVelocity = _entity->getVelocity(); - _serverAcceleration = _entity->getAcceleration(); - _serverAngularVelocity = _entity->getAngularVelocity(); + if (!_entity->shouldSuppressLocationEdits()) { + _serverPosition = _entity->getPosition(); + _serverRotation = _entity->getRotation(); + _serverVelocity = _entity->getVelocity(); + _serverAcceleration = _entity->getAcceleration(); + _serverAngularVelocity = _entity->getAngularVelocity(); + } _serverActionData = _entity->getActionData(); EntityItemProperties properties; From df5d161721b313bb9e359f0200e777ac1b60641a Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 10 Nov 2015 15:02:17 -0800 Subject: [PATCH 08/61] adjust how EntityMotionState updates its idea of what the server knows about an entity --- libraries/entities/src/EntityTree.cpp | 12 ++++++++++++ libraries/physics/src/EntityMotionState.cpp | 21 ++++++++++----------- libraries/physics/src/EntityMotionState.h | 1 + 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index f1a85a1b6d..9785e12736 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -691,6 +691,18 @@ void EntityTree::fixupTerseEditLogging(EntityItemProperties& properties, QList= 0) { + bool value = properties.getLocked(); + QString changeHint = "0"; + if (value) { + changeHint = "1"; + } + changedProperties[index] = QString("locked:") + changeHint; + } + } } int EntityTree::processEditPacketData(NLPacket& packet, const unsigned char* editData, int maxLength, diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index e61523587e..c7b72968c9 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -87,17 +87,15 @@ void EntityMotionState::updateServerPhysicsVariables(const QUuid& sessionID) { } _serverActionData = _entity->getActionData(); - - if (_entity->shouldSuppressLocationEdits()) { - // if we send now, the changes will be ignored, so don't update our idea of what the server knows. - return; + if (!_serverShouldSuppressLocationEdits) { + _serverPosition = _entity->getPosition(); + _serverRotation = _entity->getRotation(); + _serverVelocity = _entity->getVelocity(); + _serverAngularVelocity = _entity->getAngularVelocity(); + _serverAcceleration = _entity->getAcceleration(); } - _serverPosition = _entity->getPosition(); - _serverRotation = _entity->getRotation(); - _serverVelocity = _entity->getVelocity(); - _serverAngularVelocity = _entity->getAngularVelocity(); - _serverAcceleration = _entity->getAcceleration(); + _serverShouldSuppressLocationEdits = _entity->shouldSuppressLocationEdits(); } // virtual @@ -264,6 +262,7 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) { _serverAngularVelocity = bulletToGLM(_body->getAngularVelocity()); _lastStep = simulationStep; _serverActionData = _entity->getActionData(); + _serverShouldSuppressLocationEdits = _entity->shouldSuppressLocationEdits(); _sentInactive = true; return false; } @@ -447,14 +446,14 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, const Q } // remember properties for local server prediction - if (!_entity->shouldSuppressLocationEdits()) { + if (!_serverShouldSuppressLocationEdits) { _serverPosition = _entity->getPosition(); _serverRotation = _entity->getRotation(); _serverVelocity = _entity->getVelocity(); _serverAcceleration = _entity->getAcceleration(); _serverAngularVelocity = _entity->getAngularVelocity(); } - _serverActionData = _entity->getActionData(); + _serverShouldSuppressLocationEdits = _entity->shouldSuppressLocationEdits(); EntityItemProperties properties; diff --git a/libraries/physics/src/EntityMotionState.h b/libraries/physics/src/EntityMotionState.h index 188e7096b9..f70eff44a4 100644 --- a/libraries/physics/src/EntityMotionState.h +++ b/libraries/physics/src/EntityMotionState.h @@ -110,6 +110,7 @@ protected: glm::vec3 _serverGravity; glm::vec3 _serverAcceleration; QByteArray _serverActionData; + bool _serverShouldSuppressLocationEdits = false; uint32_t _lastMeasureStep; glm::vec3 _lastVelocity; From 97fec5b814a357d07dc8f065793e6697fe4b26f5 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 10 Nov 2015 15:09:53 -0800 Subject: [PATCH 09/61] adjust how EntityMotionState updates its idea of what the server knows about an entity --- libraries/physics/src/EntityMotionState.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index c7b72968c9..7c054598ab 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -445,24 +445,25 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, const Q _sentInactive = false; } - // remember properties for local server prediction + EntityItemProperties properties; + + + // explicitly set the properties that changed so that they will be packed if (!_serverShouldSuppressLocationEdits) { + // remember properties for local server prediction _serverPosition = _entity->getPosition(); _serverRotation = _entity->getRotation(); _serverVelocity = _entity->getVelocity(); _serverAcceleration = _entity->getAcceleration(); _serverAngularVelocity = _entity->getAngularVelocity(); + + properties.setPosition(_serverPosition); + properties.setRotation(_serverRotation); + properties.setVelocity(_serverVelocity); + properties.setAcceleration(_serverAcceleration); + properties.setAngularVelocity(_serverAngularVelocity); } _serverShouldSuppressLocationEdits = _entity->shouldSuppressLocationEdits(); - - EntityItemProperties properties; - - // explicitly set the properties that changed so that they will be packed - properties.setPosition(_serverPosition); - properties.setRotation(_serverRotation); - properties.setVelocity(_serverVelocity); - properties.setAcceleration(_serverAcceleration); - properties.setAngularVelocity(_serverAngularVelocity); properties.setActionData(_serverActionData); // set the LastEdited of the properties but NOT the entity itself From 774e2ab6d6338f6c6d95426ae6c9c0c3f3616288 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 10 Nov 2015 15:13:07 -0800 Subject: [PATCH 10/61] adjust how EntityMotionState updates its idea of what the server knows about an entity --- libraries/physics/src/EntityMotionState.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 7c054598ab..9be6dd38b1 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -464,6 +464,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, const Q properties.setAngularVelocity(_serverAngularVelocity); } _serverShouldSuppressLocationEdits = _entity->shouldSuppressLocationEdits(); + _serverActionData = _entity->getActionData(); properties.setActionData(_serverActionData); // set the LastEdited of the properties but NOT the entity itself From 66387c45307db73c8ef8aee357e72fb95a8a0588 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 10 Nov 2015 17:02:57 -0800 Subject: [PATCH 11/61] use icons to show network and physics status --- .../src/RenderableEntityItem.h | 11 +++++++++++ .../src/RenderableModelEntityItem.cpp | 13 +++++++++---- libraries/gpu/src/gpu/Resource.h | 2 +- .../render-utils/src/RenderDeferredTask.cpp | 9 ++++----- libraries/render/src/render/Scene.h | 2 +- libraries/render/src/render/drawItemStatus.slf | 12 ++++++++---- libraries/render/src/render/drawItemStatus.slv | 17 +++++++++++------ 7 files changed, 45 insertions(+), 21 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index 1832ef28c3..449ac40e5d 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -15,6 +15,17 @@ #include #include +// These or the icon "name" used by the render item status value, they correspond to the atlas texture used by the DrawItemStatus +// job in the current rendering pipeline defined as of now (11/2015) in render-utils/RenderDeferredTask.cpp. +enum class RenderItemStatusIcon { + PACKET_RECEIVED = 2, + PACKET_SENT = 1, + ACTIVE_IN_BULLET = 0, + SIMULATION_OWNER = 3, + + NONE = 255 +}; + class RenderableEntityItemProxy { public: diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index d33e52fa6b..83d18c0403 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -23,6 +23,7 @@ #include "EntityTreeRenderer.h" #include "EntitiesRendererLogging.h" #include "RenderableModelEntityItem.h" +#include "RenderableEntityItem.h" EntityItemPointer RenderableModelEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { return std::make_shared(entityID, properties); @@ -189,7 +190,8 @@ void makeEntityItemStatusGetters(RenderableModelEntityItem* entity, render::Item // Color is red if last update is after WAIT_THRESHOLD, green otherwise (120 deg is green) return render::Item::Status::Value(1.0f - normalizedDelta, (normalizedDelta > 1.0f ? render::Item::Status::Value::GREEN : - render::Item::Status::Value::RED)); + render::Item::Status::Value::RED), + (unsigned char) RenderItemStatusIcon::PACKET_RECEIVED); }); statusGetters.push_back([entity] () -> render::Item::Status::Value { @@ -200,15 +202,18 @@ void makeEntityItemStatusGetters(RenderableModelEntityItem* entity, render::Item // Color is Magenta if last update is after WAIT_THRESHOLD, cyan otherwise (180 deg is green) return render::Item::Status::Value(1.0f - normalizedDelta, (normalizedDelta > 1.0f ? render::Item::Status::Value::MAGENTA : - render::Item::Status::Value::CYAN)); + render::Item::Status::Value::CYAN), + (unsigned char)RenderItemStatusIcon::PACKET_SENT); }); statusGetters.push_back([entity] () -> render::Item::Status::Value { ObjectMotionState* motionState = static_cast(entity->getPhysicsInfo()); if (motionState && motionState->isActive()) { - return render::Item::Status::Value(1.0f, render::Item::Status::Value::BLUE); + return render::Item::Status::Value(1.0f, render::Item::Status::Value::BLUE, + (unsigned char)RenderItemStatusIcon::ACTIVE_IN_BULLET); } - return render::Item::Status::Value(0.0f, render::Item::Status::Value::BLUE); + return render::Item::Status::Value(0.0f, render::Item::Status::Value::BLUE, + (unsigned char)RenderItemStatusIcon::ACTIVE_IN_BULLET); }); } diff --git a/libraries/gpu/src/gpu/Resource.h b/libraries/gpu/src/gpu/Resource.h index f330b0fd07..8d53d6e2e7 100644 --- a/libraries/gpu/src/gpu/Resource.h +++ b/libraries/gpu/src/gpu/Resource.h @@ -331,7 +331,7 @@ public: template Iterator begin() { return Iterator(&edit(0), _stride); } template Iterator end() { return Iterator(&edit(getNum()), _stride); } - template Iterator cbegin() const { return Iterator(&get(0), _stride); } + template Iterator cbegin() const { return Iterator(&get(), _stride); } template Iterator cend() const { return Iterator(&get(getNum()), _stride); } // the number of elements of the specified type fitting in the view size diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index baa4b8f259..e65018ad3d 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -112,12 +112,11 @@ RenderDeferredTask::RenderDeferredTask() : Task() { _jobs.push_back(Job(new DepthSortItems::JobModel("DepthSortTransparent", _jobs.back().getOutput(), DepthSortItems(false)))); _jobs.push_back(Job(new DrawTransparentDeferred::JobModel("TransparentDeferred", _jobs.back().getOutput()))); - // Grab a texture map representing the different status icons and assign that to the drawStatsuJob - auto iconMapPath = PathUtils::resourcesPath() + "images/hifi-logo.svg"; - - auto statusIconMap = DependencyManager::get()->getImageTexture(iconMapPath); - _jobs.push_back(Job(new render::DrawStatus::JobModel("DrawStatus", renderedOpaques, DrawStatus(statusIconMap)))); + // Grab a texture map representing the different status icons and assign that to the drawStatsuJob + auto iconMapPath = PathUtils::resourcesPath() + "icons/statusIconAtlas.svg"; + auto statusIconMap = DependencyManager::get()->getImageTexture(iconMapPath); + _jobs.push_back(Job(new render::DrawStatus::JobModel("DrawStatus", renderedOpaques, DrawStatus(statusIconMap)))); _jobs.back().setEnabled(false); _drawStatusJobIndex = _jobs.size() - 1; diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 459f15055f..7176e5753e 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -212,7 +212,7 @@ public: const static Value INVALID; // Invalid value meanss the status won't show Value() {} - Value(float scale, float hue, unsigned char icon = 0) { setScale(scale); setColor(hue); setIcon(icon); } + Value(float scale, float hue, unsigned char icon = 0xFF) { setScale(scale); setColor(hue); setIcon(icon); } // It can be scaled in the range [0, 1] void setScale(float scale); diff --git a/libraries/render/src/render/drawItemStatus.slf b/libraries/render/src/render/drawItemStatus.slf index 3b902e151d..40cf450363 100644 --- a/libraries/render/src/render/drawItemStatus.slf +++ b/libraries/render/src/render/drawItemStatus.slf @@ -16,12 +16,16 @@ in vec3 varTexcoord; out vec4 outFragColor; uniform sampler2D _icons; - +vec2 getIconTexcoord(float icon, vec2 uv) { + const vec2 ICON_COORD_SIZE = vec2(0.0625, 1.0); + return vec2((uv.x + icon) * ICON_COORD_SIZE.x, uv.y * ICON_COORD_SIZE.y); +} void main(void) { - if (varTexcoord.z > 0.0f) { - outFragColor = texture(_icons, varTexcoord.xy) * varColor; + if (varTexcoord.z < 254.5) { + outFragColor = texture(_icons, getIconTexcoord(varTexcoord.z, varTexcoord.xy)) * varColor; } else { - outFragColor = varColor; + vec2 centerDir = varTexcoord.xy * 2.0f - 1.0f; + outFragColor = vec4(varColor.xyz, 1.0 - step(1.0f, dot(centerDir.xy, centerDir.xy))); } } diff --git a/libraries/render/src/render/drawItemStatus.slv b/libraries/render/src/render/drawItemStatus.slv index 8a9ca591c7..8c4f0724d5 100644 --- a/libraries/render/src/render/drawItemStatus.slv +++ b/libraries/render/src/render/drawItemStatus.slv @@ -47,11 +47,11 @@ vec3 paintRainbow(float normalizedHue) { vec3 unpackStatus(int v) { return vec3(clamp(float(int((v >> 0) & 0xFFFF) - 32727) / 32727.0, -1.0, 1.0), clamp(float(uint((v >> 16) & 0xFF)) / 255.0, 0.0, 1.0), - clamp(float(int((v >> 24) & 0xFF)), 0.0, 256.0)); + clamp(float(int((v >> 24) & 0xFF)), 0.0, 255.0)); } void main(void) { - const vec2 ICON_PIXEL_SIZE = vec2(10, 10); + const vec2 ICON_PIXEL_SIZE = vec2(20, 20); const vec2 MARGIN_PIXEL_SIZE = vec2(2, 2); const int NUM_VERTICES = 6; const vec4 UNIT_QUAD[NUM_VERTICES] = vec4[NUM_VERTICES]( @@ -79,12 +79,19 @@ void main(void) { return; } + // Which quad vertex pos? + int twoTriID = gl_VertexID - iconNum * NUM_VERTICES; + vec4 quadPos = UNIT_QUAD[twoTriID]; + // unpack to get x and y satus vec3 iconStatus = unpackStatus(inStatus[iconNum]); // Use the status for showing a color varColor = vec4(paintRainbow(abs(iconStatus.y)), 1.0); + // Pass the texcoord and the z texcoord is representing the texture icon + varTexcoord = vec3((quadPos.xy + 1.0) * 0.5, iconStatus.z); + // Also changes the size of the notification vec2 iconScale = ICON_PIXEL_SIZE; iconScale = max(vec2(0, 0), (iconScale * iconStatus.x)); @@ -93,13 +100,11 @@ void main(void) { vec2 offset = vec2(iconNum * (ICON_PIXEL_SIZE.x + MARGIN_PIXEL_SIZE.x), 0); // Final position in pixel space - int twoTriID = gl_VertexID - iconNum * NUM_VERTICES; - vec4 pos = UNIT_QUAD[twoTriID]; - vec2 quadPixelPos = offset.xy + pos.xy * 0.5 * iconScale; + vec2 quadPixelPos = offset.xy + quadPos.xy * 0.5 * iconScale; vec4 viewport; <$transformCameraViewport(cam, viewport)$>; vec2 pixelToClip = vec2(2.0 / viewport.z, 2.0 / viewport.w); gl_Position = anchorPoint + (anchorPoint.w * vec4(quadPixelPos * pixelToClip, 0.0, 0.0)); -} \ No newline at end of file +} From 39b92d2b5297d9d3edf0225a720ad6b5a8e0e526 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 10 Nov 2015 17:06:12 -0800 Subject: [PATCH 12/61] terse log when ownership changes --- .../entities-renderer/src/RenderableEntityItem.cpp | 4 +--- libraries/entities-renderer/src/RenderableEntityItem.h | 1 + .../src/RenderableModelEntityItem.cpp | 4 ++-- .../src/RenderableParticleEffectEntityItem.cpp | 3 +++ .../src/RenderablePolyVoxEntityItem.cpp | 4 ++++ .../entities-renderer/src/RenderableZoneEntityItem.cpp | 10 +++++++++- libraries/entities/src/EntityTree.cpp | 7 +++++++ 7 files changed, 27 insertions(+), 6 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index bf9710857a..177095c673 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -10,6 +10,7 @@ // +#include #include "RenderableEntityItem.h" namespace render { @@ -39,6 +40,3 @@ namespace render { } } } - - - diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index 1832ef28c3..26d00c9bdb 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -62,5 +62,6 @@ private: \ SimpleRenderableEntityItem _renderHelper; +void makeEntityItemStatusGetters(EntityItem* entity, render::Item::Status::Getters& statusGetters); #endif // hifi_RenderableEntityItem_h diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index d33e52fa6b..32be9707c6 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -18,10 +18,10 @@ #include #include #include -#include #include "EntityTreeRenderer.h" #include "EntitiesRendererLogging.h" +#include "RenderableEntityItem.h" #include "RenderableModelEntityItem.h" EntityItemPointer RenderableModelEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { @@ -180,7 +180,7 @@ namespace render { } } -void makeEntityItemStatusGetters(RenderableModelEntityItem* entity, render::Item::Status::Getters& statusGetters) { +void makeEntityItemStatusGetters(EntityItem* entity, render::Item::Status::Getters& statusGetters) { statusGetters.push_back([entity] () -> render::Item::Status::Value { quint64 delta = usecTimestampNow() - entity->getLastEditedFromRemote(); const float WAIT_THRESHOLD_INV = 1.0f / (0.2f * USECS_PER_SECOND); diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 41cf3b9bbf..ecb16424d6 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -139,6 +139,9 @@ bool RenderableParticleEffectEntityItem::addToScene(EntityItemPointer self, _renderItemId = scene->allocateID(); auto renderData = ParticlePayload::Pointer(particlePayload); auto renderPayload = render::PayloadPointer(new ParticlePayload::Payload(renderData)); + render::Item::Status::Getters statusGetters; + makeEntityItemStatusGetters(this, statusGetters); + renderPayload->addStatusGetters(statusGetters); pendingChanges.resetItem(_renderItemId, renderPayload); _scene = scene; return true; diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index cd88638e51..a4e20bfcf9 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -549,6 +549,10 @@ bool RenderablePolyVoxEntityItem::addToScene(EntityItemPointer self, auto renderData = PolyVoxPayload::Pointer(renderItem); auto renderPayload = std::make_shared(renderData); + render::Item::Status::Getters statusGetters; + makeEntityItemStatusGetters(this, statusGetters); + renderPayload->addStatusGetters(statusGetters); + pendingChanges.resetItem(_myItem, renderPayload); return true; diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index 62d98f3322..8b2a2d33df 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -19,6 +19,8 @@ #include #include +#include "RenderableEntityItem.h" + // Sphere entities should fit inside a cube entity of the same size, so a sphere that has dimensions 1x1x1 // is a half unit sphere. However, the geometry cache renders a UNIT sphere, so we need to scale down. static const float SPHERE_ENTITY_SCALE = 0.5f; @@ -112,6 +114,8 @@ void RenderableZoneEntityItem::render(RenderArgs* args) { render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); render::PendingChanges pendingChanges; _model->removeFromScene(scene, pendingChanges); + render::Item::Status::Getters statusGetters; + makeEntityItemStatusGetters(this, statusGetters); _model->addToScene(scene, pendingChanges, false); scene->enqueuePendingChanges(pendingChanges); @@ -203,7 +207,11 @@ bool RenderableZoneEntityItem::addToScene(EntityItemPointer self, std::shared_pt auto renderData = std::make_shared(self); auto renderPayload = std::make_shared(renderData); - + + render::Item::Status::Getters statusGetters; + makeEntityItemStatusGetters(this, statusGetters); + renderPayload->addStatusGetters(statusGetters); + pendingChanges.resetItem(_myMetaItem, renderPayload); return true; } diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 9785e12736..40fbca26bd 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -198,6 +198,13 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI properties.setAngularVelocityChanged(false); properties.setAccelerationChanged(false); } + + if (wantTerseEditLogging()) { + if (properties.simulationOwnerChanged()) { + QString itemName = entity->getName() != "" ? entity->getName() : entity->getID().toString(); + qCDebug(entities) << "sim ownership for" << itemName << "is now" << senderID; + } + } } // else client accepts what the server says From 4cf84a4e5b940bc7ac61d3f3d8ed615a9e1590b9 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 10 Nov 2015 17:14:09 -0800 Subject: [PATCH 13/61] use makeEntityItemStatusGetters from more entity types --- .../src/RenderableEntityItem.cpp | 36 +++++++++++++++++++ .../src/RenderableModelEntityItem.cpp | 36 ------------------- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index 177095c673..e55ba44487 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -40,3 +40,39 @@ namespace render { } } } + +void makeEntityItemStatusGetters(EntityItem* entity, render::Item::Status::Getters& statusGetters) { + statusGetters.push_back([entity] () -> render::Item::Status::Value { + quint64 delta = usecTimestampNow() - entity->getLastEditedFromRemote(); + const float WAIT_THRESHOLD_INV = 1.0f / (0.2f * USECS_PER_SECOND); + float normalizedDelta = delta * WAIT_THRESHOLD_INV; + // Status icon will scale from 1.0f down to 0.0f after WAIT_THRESHOLD + // Color is red if last update is after WAIT_THRESHOLD, green otherwise (120 deg is green) + return render::Item::Status::Value(1.0f - normalizedDelta, (normalizedDelta > 1.0f ? + render::Item::Status::Value::GREEN : + render::Item::Status::Value::RED), + (unsigned char) RenderItemStatusIcon::PACKET_RECEIVED); + }); + + statusGetters.push_back([entity] () -> render::Item::Status::Value { + quint64 delta = usecTimestampNow() - entity->getLastBroadcast(); + const float WAIT_THRESHOLD_INV = 1.0f / (0.4f * USECS_PER_SECOND); + float normalizedDelta = delta * WAIT_THRESHOLD_INV; + // Status icon will scale from 1.0f down to 0.0f after WAIT_THRESHOLD + // Color is Magenta if last update is after WAIT_THRESHOLD, cyan otherwise (180 deg is green) + return render::Item::Status::Value(1.0f - normalizedDelta, (normalizedDelta > 1.0f ? + render::Item::Status::Value::MAGENTA : + render::Item::Status::Value::CYAN), + (unsigned char)RenderItemStatusIcon::PACKET_SENT); + }); + + statusGetters.push_back([entity] () -> render::Item::Status::Value { + ObjectMotionState* motionState = static_cast(entity->getPhysicsInfo()); + if (motionState && motionState->isActive()) { + return render::Item::Status::Value(1.0f, render::Item::Status::Value::BLUE, + (unsigned char)RenderItemStatusIcon::ACTIVE_IN_BULLET); + } + return render::Item::Status::Value(0.0f, render::Item::Status::Value::BLUE, + (unsigned char)RenderItemStatusIcon::ACTIVE_IN_BULLET); + }); +} diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index fdbb549cdb..a9cb19e2ff 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -181,42 +181,6 @@ namespace render { } } -void makeEntityItemStatusGetters(EntityItem* entity, render::Item::Status::Getters& statusGetters) { - statusGetters.push_back([entity] () -> render::Item::Status::Value { - quint64 delta = usecTimestampNow() - entity->getLastEditedFromRemote(); - const float WAIT_THRESHOLD_INV = 1.0f / (0.2f * USECS_PER_SECOND); - float normalizedDelta = delta * WAIT_THRESHOLD_INV; - // Status icon will scale from 1.0f down to 0.0f after WAIT_THRESHOLD - // Color is red if last update is after WAIT_THRESHOLD, green otherwise (120 deg is green) - return render::Item::Status::Value(1.0f - normalizedDelta, (normalizedDelta > 1.0f ? - render::Item::Status::Value::GREEN : - render::Item::Status::Value::RED), - (unsigned char) RenderItemStatusIcon::PACKET_RECEIVED); - }); - - statusGetters.push_back([entity] () -> render::Item::Status::Value { - quint64 delta = usecTimestampNow() - entity->getLastBroadcast(); - const float WAIT_THRESHOLD_INV = 1.0f / (0.4f * USECS_PER_SECOND); - float normalizedDelta = delta * WAIT_THRESHOLD_INV; - // Status icon will scale from 1.0f down to 0.0f after WAIT_THRESHOLD - // Color is Magenta if last update is after WAIT_THRESHOLD, cyan otherwise (180 deg is green) - return render::Item::Status::Value(1.0f - normalizedDelta, (normalizedDelta > 1.0f ? - render::Item::Status::Value::MAGENTA : - render::Item::Status::Value::CYAN), - (unsigned char)RenderItemStatusIcon::PACKET_SENT); - }); - - statusGetters.push_back([entity] () -> render::Item::Status::Value { - ObjectMotionState* motionState = static_cast(entity->getPhysicsInfo()); - if (motionState && motionState->isActive()) { - return render::Item::Status::Value(1.0f, render::Item::Status::Value::BLUE, - (unsigned char)RenderItemStatusIcon::ACTIVE_IN_BULLET); - } - return render::Item::Status::Value(0.0f, render::Item::Status::Value::BLUE, - (unsigned char)RenderItemStatusIcon::ACTIVE_IN_BULLET); - }); -} - bool RenderableModelEntityItem::addToScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { _myMetaItem = scene->allocateID(); From 3557eacbd05d9c3fe28f53e00e6d5ebf41102999 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 10 Nov 2015 18:18:29 -0800 Subject: [PATCH 14/61] Add QTryRead/WriteLocker classes --- libraries/shared/src/shared/QTryReadLocker.h | 92 +++++++++++++++++++ libraries/shared/src/shared/QTryWriteLocker.h | 92 +++++++++++++++++++ 2 files changed, 184 insertions(+) create mode 100644 libraries/shared/src/shared/QTryReadLocker.h create mode 100644 libraries/shared/src/shared/QTryWriteLocker.h diff --git a/libraries/shared/src/shared/QTryReadLocker.h b/libraries/shared/src/shared/QTryReadLocker.h new file mode 100644 index 0000000000..573eba61b8 --- /dev/null +++ b/libraries/shared/src/shared/QTryReadLocker.h @@ -0,0 +1,92 @@ +// +// QTryReadLocker.h +// shared/src/shared/QTryReadLocker.h +// +// Created by Clément Brisset on 10/29/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 +// + +#ifndef hifi_QTryReadLocker_h +#define hifi_QTryReadLocker_h + +#include + +class QTryReadLocker { +public: + QTryReadLocker(QReadWriteLock* readWriteLock); + QTryReadLocker(QReadWriteLock* readWriteLock, int timeout); + ~QTryReadLocker(); + + bool isLocked() const; + + void unlock(); + bool tryRelock(); + bool tryRelock(int timeout); + + QReadWriteLock* readWriteLock() const; + +private: + Q_DISABLE_COPY(QTryReadLocker) + quintptr q_val; +}; + +// Implementation +inline QTryReadLocker::QTryReadLocker(QReadWriteLock *areadWriteLock) : + q_val(reinterpret_cast(areadWriteLock)) +{ + Q_ASSERT_X((q_val & quintptr(1u)) == quintptr(0), + "QTryReadLocker", "QTryReadLocker pointer is misaligned"); + tryRelock(); +} + +inline QTryReadLocker::QTryReadLocker(QReadWriteLock *areadWriteLock, int timeout) : + q_val(reinterpret_cast(areadWriteLock)) +{ + Q_ASSERT_X((q_val & quintptr(1u)) == quintptr(0), + "QTryReadLocker", "QTryReadLocker pointer is misaligned"); + tryRelock(timeout); +} + +inline QTryReadLocker::~QTryReadLocker() { + unlock(); +} + +inline bool QTryReadLocker::isLocked() const { + return (q_val & quintptr(1u)) == quintptr(1u); +} + +inline void QTryReadLocker::unlock() { + if (q_val && isLocked()) { + q_val &= ~quintptr(1u); + readWriteLock()->unlock(); + } +} + +inline bool QTryReadLocker::tryRelock() { + if (q_val && !isLocked()) { + if (readWriteLock()->tryLockForRead()) { + q_val |= quintptr(1u); + return true; + } + } + return false; +} + +inline bool QTryReadLocker::tryRelock(int timeout) { + if (q_val && !isLocked()) { + if (readWriteLock()->tryLockForRead(timeout)) { + q_val |= quintptr(1u); + return true; + } + } + return false; +} + +inline QReadWriteLock* QTryReadLocker::readWriteLock() const { + return reinterpret_cast(q_val & ~quintptr(1u)); +} + +#endif // hifi_QTryReadLocker_h \ No newline at end of file diff --git a/libraries/shared/src/shared/QTryWriteLocker.h b/libraries/shared/src/shared/QTryWriteLocker.h new file mode 100644 index 0000000000..319920f724 --- /dev/null +++ b/libraries/shared/src/shared/QTryWriteLocker.h @@ -0,0 +1,92 @@ +// +// QTryWriteLocker.h +// shared/src/shared/QTryWriteLocker.h +// +// Created by Clément Brisset on 10/29/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 +// + +#ifndef hifi_QTryWriteLocker_h +#define hifi_QTryWriteLocker_h + +#include + +class QTryWriteLocker { +public: + QTryWriteLocker(QReadWriteLock* readWriteLock); + QTryWriteLocker(QReadWriteLock* readWriteLock, int timeout); + ~QTryWriteLocker(); + + bool isLocked() const; + + void unlock(); + bool tryRelock(); + bool tryRelock(int timeout); + + QReadWriteLock* readWriteLock() const; + +private: + Q_DISABLE_COPY(QTryWriteLocker) + quintptr q_val; +}; + +// Implementation +inline QTryWriteLocker::QTryWriteLocker(QReadWriteLock *readWriteLock) : + q_val(reinterpret_cast(readWriteLock)) +{ + Q_ASSERT_X((q_val & quintptr(1u)) == quintptr(0), + "QTryWriteLocker", "QTryWriteLocker pointer is misaligned"); + tryRelock(); +} + +inline QTryWriteLocker::QTryWriteLocker(QReadWriteLock *readWriteLock, int timeout) : + q_val(reinterpret_cast(readWriteLock)) +{ + Q_ASSERT_X((q_val & quintptr(1u)) == quintptr(0), + "QTryWriteLocker", "QTryWriteLocker pointer is misaligned"); + tryRelock(timeout); +} + +inline QTryWriteLocker::~QTryWriteLocker() { + unlock(); +} + +inline bool QTryWriteLocker::isLocked() const { + return (q_val & quintptr(1u)) == quintptr(1u); +} + +inline void QTryWriteLocker::unlock() { + if (q_val && isLocked()) { + q_val &= ~quintptr(1u); + readWriteLock()->unlock(); + } +} + +inline bool QTryWriteLocker::tryRelock() { + if (q_val && !isLocked()) { + if (readWriteLock()->tryLockForWrite()) { + q_val |= quintptr(1u); + return true; + } + } + return false; +} + +inline bool QTryWriteLocker::tryRelock(int timeout) { + if (q_val && !isLocked()) { + if (readWriteLock()->tryLockForWrite(timeout)) { + q_val |= quintptr(1u); + return true; + } + } + return false; +} + +inline QReadWriteLock* QTryWriteLocker::readWriteLock() const { + return reinterpret_cast(q_val & ~quintptr(1u)); +} + +#endif // hifi_QTryWriteLocker_h \ No newline at end of file From 7cf2ad22155ddde62a16f660078b2f165ce59081 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 10 Nov 2015 18:19:12 -0800 Subject: [PATCH 15/61] Remove lockFor... and expand ReadWriteLockable --- .../shared/src/shared/ReadWriteLockable.h | 136 +++++++++++++----- 1 file changed, 100 insertions(+), 36 deletions(-) diff --git a/libraries/shared/src/shared/ReadWriteLockable.h b/libraries/shared/src/shared/ReadWriteLockable.h index 98dff4a841..04aa20a067 100644 --- a/libraries/shared/src/shared/ReadWriteLockable.h +++ b/libraries/shared/src/shared/ReadWriteLockable.h @@ -9,54 +9,118 @@ #pragma once #ifndef hifi_ReadWriteLockable_h #define hifi_ReadWriteLockable_h + +#include + #include +#include "QTryReadLocker.h" +#include "QTryWriteLocker.h" + class ReadWriteLockable { public: + // Write locks template - bool withWriteLock(F f, bool require = true) const { - if (!require) { - bool result = _lock.tryLockForWrite(); - if (result) { - f(); - _lock.unlock(); - } - return result; - } - - QWriteLocker locker(&_lock); - f(); - return true; - } + bool withWriteLock(F f) const; + + template + bool withWriteLock(F&& f, bool require) const; template - bool withTryWriteLock(F f) const { - return withWriteLock(f, false); - } - + bool withTryWriteLock(F f) const; + template - bool withReadLock(F f, bool require = true) const { - if (!require) { - bool result = _lock.tryLockForRead(); - if (result) { - f(); - _lock.unlock(); - } - return result; - } - - QReadLocker locker(&_lock); - f(); - return true; - } - + bool withTryWriteLock(F f, int timeout) const; + + // Read locks template - bool withTryReadLock(F f) const { - return withReadLock(f, false); - } + bool withReadLock(F f) const; + + template + bool withReadLock(F&& f, bool require) const; + + template + bool withTryReadLock(F f) const; + + template + bool withTryReadLock(F f, int timeout) const; private: mutable QReadWriteLock _lock{ QReadWriteLock::Recursive }; }; +// ReadWriteLockable +template +inline bool ReadWriteLockable::withWriteLock(F f) const { + QWriteLocker locker(&_lock); + f(); + return true; +} + +template +inline bool ReadWriteLockable::withWriteLock(F&& f, bool require) const { + if (require) { + return withWriteLock(std::forward(f)); + } else { + return withTryReadLock(std::forward(f)); + } +} + +template +inline bool ReadWriteLockable::withTryWriteLock(F f) const { + QTryWriteLocker locker(&_lock); + if (locker.isLocked()) { + f(); + return true; + } + return false; +} + +template +inline bool ReadWriteLockable::withTryWriteLock(F f, int timeout) const { + QTryWriteLocker locker(&_lock, timeout); + if (locker.isLocked()) { + f(); + return true; + } + return false; +} + +template +inline bool ReadWriteLockable::withReadLock(F f) const { + QReadLocker locker(&_lock); + f(); + return true; +} + +template +inline bool ReadWriteLockable::withReadLock(F&& f, bool require) const { + if (require) { + return withReadLock(std::forward(f)); + } else { + return withTryReadLock(std::forward(f)); + } +} + +template +inline bool ReadWriteLockable::withTryReadLock(F f) const { + QTryReadLocker locker(&_lock); + if (locker.isLocked()) { + f(); + return true; + } + return false; +} + +template +inline bool ReadWriteLockable::withTryReadLock(F f, int timeout) const { + QTryReadLocker locker(&_lock, timeout); + if (locker.isLocked()) { + f(); + return true; + } + return false; +} + + #endif From 4d8fa58dd3a0c5996e8623b72c2dfd5a894eaa4f Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 10 Nov 2015 18:22:30 -0800 Subject: [PATCH 16/61] Coding standard --- libraries/shared/src/shared/QTryReadLocker.h | 30 +++++++++---------- libraries/shared/src/shared/QTryWriteLocker.h | 30 +++++++++---------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/libraries/shared/src/shared/QTryReadLocker.h b/libraries/shared/src/shared/QTryReadLocker.h index 573eba61b8..a9ab2a1e68 100644 --- a/libraries/shared/src/shared/QTryReadLocker.h +++ b/libraries/shared/src/shared/QTryReadLocker.h @@ -30,22 +30,22 @@ public: private: Q_DISABLE_COPY(QTryReadLocker) - quintptr q_val; + quintptr _val; }; // Implementation -inline QTryReadLocker::QTryReadLocker(QReadWriteLock *areadWriteLock) : - q_val(reinterpret_cast(areadWriteLock)) +inline QTryReadLocker::QTryReadLocker(QReadWriteLock* areadWriteLock) : + _val(reinterpret_cast(areadWriteLock)) { - Q_ASSERT_X((q_val & quintptr(1u)) == quintptr(0), + Q_ASSERT_X((_val & quintptr(1u)) == quintptr(0), "QTryReadLocker", "QTryReadLocker pointer is misaligned"); tryRelock(); } -inline QTryReadLocker::QTryReadLocker(QReadWriteLock *areadWriteLock, int timeout) : - q_val(reinterpret_cast(areadWriteLock)) +inline QTryReadLocker::QTryReadLocker(QReadWriteLock* areadWriteLock, int timeout) : + _val(reinterpret_cast(areadWriteLock)) { - Q_ASSERT_X((q_val & quintptr(1u)) == quintptr(0), + Q_ASSERT_X((_val & quintptr(1u)) == quintptr(0), "QTryReadLocker", "QTryReadLocker pointer is misaligned"); tryRelock(timeout); } @@ -55,20 +55,20 @@ inline QTryReadLocker::~QTryReadLocker() { } inline bool QTryReadLocker::isLocked() const { - return (q_val & quintptr(1u)) == quintptr(1u); + return (_val & quintptr(1u)) == quintptr(1u); } inline void QTryReadLocker::unlock() { - if (q_val && isLocked()) { - q_val &= ~quintptr(1u); + if (_val && isLocked()) { + _val &= ~quintptr(1u); readWriteLock()->unlock(); } } inline bool QTryReadLocker::tryRelock() { - if (q_val && !isLocked()) { + if (_val && !isLocked()) { if (readWriteLock()->tryLockForRead()) { - q_val |= quintptr(1u); + _val |= quintptr(1u); return true; } } @@ -76,9 +76,9 @@ inline bool QTryReadLocker::tryRelock() { } inline bool QTryReadLocker::tryRelock(int timeout) { - if (q_val && !isLocked()) { + if (_val && !isLocked()) { if (readWriteLock()->tryLockForRead(timeout)) { - q_val |= quintptr(1u); + _val |= quintptr(1u); return true; } } @@ -86,7 +86,7 @@ inline bool QTryReadLocker::tryRelock(int timeout) { } inline QReadWriteLock* QTryReadLocker::readWriteLock() const { - return reinterpret_cast(q_val & ~quintptr(1u)); + return reinterpret_cast(_val & ~quintptr(1u)); } #endif // hifi_QTryReadLocker_h \ No newline at end of file diff --git a/libraries/shared/src/shared/QTryWriteLocker.h b/libraries/shared/src/shared/QTryWriteLocker.h index 319920f724..cbfc335da1 100644 --- a/libraries/shared/src/shared/QTryWriteLocker.h +++ b/libraries/shared/src/shared/QTryWriteLocker.h @@ -30,22 +30,22 @@ public: private: Q_DISABLE_COPY(QTryWriteLocker) - quintptr q_val; + quintptr _val; }; // Implementation -inline QTryWriteLocker::QTryWriteLocker(QReadWriteLock *readWriteLock) : - q_val(reinterpret_cast(readWriteLock)) +inline QTryWriteLocker::QTryWriteLocker(QReadWriteLock* readWriteLock) : + _val(reinterpret_cast(readWriteLock)) { - Q_ASSERT_X((q_val & quintptr(1u)) == quintptr(0), + Q_ASSERT_X((_val & quintptr(1u)) == quintptr(0), "QTryWriteLocker", "QTryWriteLocker pointer is misaligned"); tryRelock(); } -inline QTryWriteLocker::QTryWriteLocker(QReadWriteLock *readWriteLock, int timeout) : - q_val(reinterpret_cast(readWriteLock)) +inline QTryWriteLocker::QTryWriteLocker(QReadWriteLock* readWriteLock, int timeout) : + _val(reinterpret_cast(readWriteLock)) { - Q_ASSERT_X((q_val & quintptr(1u)) == quintptr(0), + Q_ASSERT_X((_val & quintptr(1u)) == quintptr(0), "QTryWriteLocker", "QTryWriteLocker pointer is misaligned"); tryRelock(timeout); } @@ -55,20 +55,20 @@ inline QTryWriteLocker::~QTryWriteLocker() { } inline bool QTryWriteLocker::isLocked() const { - return (q_val & quintptr(1u)) == quintptr(1u); + return (_val & quintptr(1u)) == quintptr(1u); } inline void QTryWriteLocker::unlock() { - if (q_val && isLocked()) { - q_val &= ~quintptr(1u); + if (_val && isLocked()) { + _val &= ~quintptr(1u); readWriteLock()->unlock(); } } inline bool QTryWriteLocker::tryRelock() { - if (q_val && !isLocked()) { + if (_val && !isLocked()) { if (readWriteLock()->tryLockForWrite()) { - q_val |= quintptr(1u); + _val |= quintptr(1u); return true; } } @@ -76,9 +76,9 @@ inline bool QTryWriteLocker::tryRelock() { } inline bool QTryWriteLocker::tryRelock(int timeout) { - if (q_val && !isLocked()) { + if (_val && !isLocked()) { if (readWriteLock()->tryLockForWrite(timeout)) { - q_val |= quintptr(1u); + _val |= quintptr(1u); return true; } } @@ -86,7 +86,7 @@ inline bool QTryWriteLocker::tryRelock(int timeout) { } inline QReadWriteLock* QTryWriteLocker::readWriteLock() const { - return reinterpret_cast(q_val & ~quintptr(1u)); + return reinterpret_cast(_val & ~quintptr(1u)); } #endif // hifi_QTryWriteLocker_h \ No newline at end of file From d5c44466c4af7d281d630557df9b41d7aaf13b76 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 10 Nov 2015 18:24:41 -0800 Subject: [PATCH 17/61] Take Callables with rvalue ref --- .../shared/src/shared/ReadWriteLockable.h | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/libraries/shared/src/shared/ReadWriteLockable.h b/libraries/shared/src/shared/ReadWriteLockable.h index 04aa20a067..9279628e10 100644 --- a/libraries/shared/src/shared/ReadWriteLockable.h +++ b/libraries/shared/src/shared/ReadWriteLockable.h @@ -21,37 +21,37 @@ class ReadWriteLockable { public: // Write locks template - bool withWriteLock(F f) const; + bool withWriteLock(F&& f) const; template bool withWriteLock(F&& f, bool require) const; template - bool withTryWriteLock(F f) const; + bool withTryWriteLock(F&& f) const; template - bool withTryWriteLock(F f, int timeout) const; + bool withTryWriteLock(F&& f, int timeout) const; // Read locks template - bool withReadLock(F f) const; + bool withReadLock(F&& f) const; template bool withReadLock(F&& f, bool require) const; template - bool withTryReadLock(F f) const; + bool withTryReadLock(F&& f) const; template - bool withTryReadLock(F f, int timeout) const; + bool withTryReadLock(F&& f, int timeout) const; private: - mutable QReadWriteLock _lock{ QReadWriteLock::Recursive }; + mutable QReadWriteLock _lock { QReadWriteLock::Recursive }; }; // ReadWriteLockable template -inline bool ReadWriteLockable::withWriteLock(F f) const { +inline bool ReadWriteLockable::withWriteLock(F&& f) const { QWriteLocker locker(&_lock); f(); return true; @@ -67,7 +67,7 @@ inline bool ReadWriteLockable::withWriteLock(F&& f, bool require) const { } template -inline bool ReadWriteLockable::withTryWriteLock(F f) const { +inline bool ReadWriteLockable::withTryWriteLock(F&& f) const { QTryWriteLocker locker(&_lock); if (locker.isLocked()) { f(); @@ -77,7 +77,7 @@ inline bool ReadWriteLockable::withTryWriteLock(F f) const { } template -inline bool ReadWriteLockable::withTryWriteLock(F f, int timeout) const { +inline bool ReadWriteLockable::withTryWriteLock(F&& f, int timeout) const { QTryWriteLocker locker(&_lock, timeout); if (locker.isLocked()) { f(); @@ -87,7 +87,7 @@ inline bool ReadWriteLockable::withTryWriteLock(F f, int timeout) const { } template -inline bool ReadWriteLockable::withReadLock(F f) const { +inline bool ReadWriteLockable::withReadLock(F&& f) const { QReadLocker locker(&_lock); f(); return true; @@ -103,7 +103,7 @@ inline bool ReadWriteLockable::withReadLock(F&& f, bool require) const { } template -inline bool ReadWriteLockable::withTryReadLock(F f) const { +inline bool ReadWriteLockable::withTryReadLock(F&& f) const { QTryReadLocker locker(&_lock); if (locker.isLocked()) { f(); @@ -113,7 +113,7 @@ inline bool ReadWriteLockable::withTryReadLock(F f) const { } template -inline bool ReadWriteLockable::withTryReadLock(F f, int timeout) const { +inline bool ReadWriteLockable::withTryReadLock(F&& f, int timeout) const { QTryReadLocker locker(&_lock, timeout); if (locker.isLocked()) { f(); From 65e9dc4be556fc58abdc48bc77983a92465d1b79 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 10 Nov 2015 18:39:59 -0800 Subject: [PATCH 18/61] Fixup return types --- libraries/shared/src/shared/ReadWriteLockable.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libraries/shared/src/shared/ReadWriteLockable.h b/libraries/shared/src/shared/ReadWriteLockable.h index 9279628e10..07b46bb92a 100644 --- a/libraries/shared/src/shared/ReadWriteLockable.h +++ b/libraries/shared/src/shared/ReadWriteLockable.h @@ -21,7 +21,7 @@ class ReadWriteLockable { public: // Write locks template - bool withWriteLock(F&& f) const; + void withWriteLock(F&& f) const; template bool withWriteLock(F&& f, bool require) const; @@ -34,7 +34,7 @@ public: // Read locks template - bool withReadLock(F&& f) const; + void withReadLock(F&& f) const; template bool withReadLock(F&& f, bool require) const; @@ -51,16 +51,16 @@ private: // ReadWriteLockable template -inline bool ReadWriteLockable::withWriteLock(F&& f) const { +inline void ReadWriteLockable::withWriteLock(F&& f) const { QWriteLocker locker(&_lock); f(); - return true; } template inline bool ReadWriteLockable::withWriteLock(F&& f, bool require) const { if (require) { - return withWriteLock(std::forward(f)); + withWriteLock(std::forward(f)); + return true; } else { return withTryReadLock(std::forward(f)); } @@ -87,16 +87,16 @@ inline bool ReadWriteLockable::withTryWriteLock(F&& f, int timeout) const { } template -inline bool ReadWriteLockable::withReadLock(F&& f) const { +inline void ReadWriteLockable::withReadLock(F&& f) const { QReadLocker locker(&_lock); f(); - return true; } template inline bool ReadWriteLockable::withReadLock(F&& f, bool require) const { if (require) { - return withReadLock(std::forward(f)); + withReadLock(std::forward(f)); + return true; } else { return withTryReadLock(std::forward(f)); } From b38c1cb30f9fce0f9fe24430ceadb6390697af7c Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 11 Nov 2015 08:01:21 -0800 Subject: [PATCH 19/61] add icons --- interface/resources/icons/statusIconAtlas.svg | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 interface/resources/icons/statusIconAtlas.svg diff --git a/interface/resources/icons/statusIconAtlas.svg b/interface/resources/icons/statusIconAtlas.svg new file mode 100644 index 0000000000..3e15da10cb --- /dev/null +++ b/interface/resources/icons/statusIconAtlas.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + From c2b0ccd6b395ec6a5729adfc17f0cac15f98a4d1 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 11 Nov 2015 08:30:04 -0800 Subject: [PATCH 20/61] show simulation ownership with status icons --- .../src/RenderableEntityItem.cpp | 13 ++++++++++++ .../src/RenderableEntityItem.h | 21 +++++++++---------- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index e55ba44487..ea6f004b30 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -75,4 +75,17 @@ void makeEntityItemStatusGetters(EntityItem* entity, render::Item::Status::Gette return render::Item::Status::Value(0.0f, render::Item::Status::Value::BLUE, (unsigned char)RenderItemStatusIcon::ACTIVE_IN_BULLET); }); + + statusGetters.push_back([entity] () -> render::Item::Status::Value { + auto nodeList = DependencyManager::get(); + const QUuid& myNodeID = nodeList->getSessionUUID(); + bool weOwnSimulation = entity->getSimulationOwner().matchesValidID(myNodeID); + + if (weOwnSimulation) { + return render::Item::Status::Value(1.0f, render::Item::Status::Value::BLUE, + (unsigned char)RenderItemStatusIcon::SIMULATION_OWNER); + } + return render::Item::Status::Value(0.0f, render::Item::Status::Value::BLUE, + (unsigned char)RenderItemStatusIcon::SIMULATION_OWNER); + }); } diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index 254a76d291..4da8ff1b4c 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -18,12 +18,11 @@ // These or the icon "name" used by the render item status value, they correspond to the atlas texture used by the DrawItemStatus // job in the current rendering pipeline defined as of now (11/2015) in render-utils/RenderDeferredTask.cpp. enum class RenderItemStatusIcon { - PACKET_RECEIVED = 2, - PACKET_SENT = 1, - ACTIVE_IN_BULLET = 0, - SIMULATION_OWNER = 3, - - NONE = 255 + ACTIVE_IN_BULLET = 0, + PACKET_SENT = 1, + PACKET_RECEIVED = 2, + SIMULATION_OWNER = 3, + NONE = 255 }; @@ -32,7 +31,7 @@ public: RenderableEntityItemProxy(EntityItemPointer entity) : entity(entity) { } typedef render::Payload Payload; typedef Payload::DataPointer Pointer; - + EntityItemPointer entity; }; @@ -47,19 +46,19 @@ class SimpleRenderableEntityItem { public: bool addToScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { _myItem = scene->allocateID(); - + auto renderData = std::make_shared(self); auto renderPayload = std::make_shared(renderData); - + pendingChanges.resetItem(_myItem, renderPayload); - + return true; } void removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { pendingChanges.removeItem(_myItem); } - + private: render::ItemID _myItem; }; From 31ebe5dba1f210203705e249b4e01f1296fadf6c Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 11 Nov 2015 08:51:10 -0800 Subject: [PATCH 21/61] terse logging for sim ownership --- libraries/entities/src/EntityItem.cpp | 24 ++++++++++++++++++++++-- libraries/entities/src/EntityItem.h | 2 ++ libraries/entities/src/EntityTree.cpp | 15 ++++++--------- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index dbea43d514..8aa2bdb5d3 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -632,6 +632,9 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef if (_simulationOwner.set(newSimOwner)) { _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; + if (wantTerseEditLogging()) { + qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << newSimOwner; + } } } { // When we own the simulation we don't accept updates to the entity's transform/velocities @@ -996,6 +999,11 @@ EntityTreePointer EntityItem::getTree() const { return tree; } +bool EntityItem::wantTerseEditLogging() { + EntityTreePointer tree = getTree(); + return tree ? tree->wantTerseEditLogging() : false; +} + glm::mat4 EntityItem::getEntityToWorldMatrix() const { glm::mat4 translation = glm::translate(getPosition()); glm::mat4 rotation = glm::mat4_cast(getRotation()); @@ -1492,21 +1500,33 @@ void EntityItem::updateCreated(uint64_t value) { } void EntityItem::setSimulationOwner(const QUuid& id, quint8 priority) { - _simulationOwner.set(id, priority); + if (_simulationOwner.set(id, priority)) { + if (wantTerseEditLogging()) { + qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << id; + } + } } void EntityItem::setSimulationOwner(const SimulationOwner& owner) { - _simulationOwner.set(owner); + if (_simulationOwner.set(owner)) { + if (wantTerseEditLogging()) { + qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << owner; + } + } } void EntityItem::updateSimulatorID(const QUuid& value) { if (_simulationOwner.setID(value)) { _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; + if (wantTerseEditLogging()) { + qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << value; + } } } void EntityItem::clearSimulationOwnership() { _simulationOwner.clear(); + qCDebug(entities) << "sim ownership for" << getDebugName() << "is now null"; // don't bother setting the DIRTY_SIMULATOR_ID flag because clearSimulationOwnership() // is only ever called entity-server-side and the flags are only used client-side //_dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 858dc7e326..b3c976c1ca 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -307,6 +307,7 @@ public: QString getName() const { return _name; } void setName(const QString& value) { _name = value; } + QString getDebugName() { return _name != "" ? _name : getID().toString(); } bool getVisible() const { return _visible; } void setVisible(bool value) { _visible = value; } @@ -381,6 +382,7 @@ public: void setPhysicsInfo(void* data) { _physicsInfo = data; } EntityTreeElementPointer getElement() const { return _element; } EntityTreePointer getTree() const; + bool wantTerseEditLogging(); static void setSendPhysicsUpdates(bool value) { _sendPhysicsUpdates = value; } static bool getSendPhysicsUpdates() { return _sendPhysicsUpdates; } diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 40fbca26bd..179e68ea29 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -199,12 +199,11 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI properties.setAccelerationChanged(false); } - if (wantTerseEditLogging()) { - if (properties.simulationOwnerChanged()) { - QString itemName = entity->getName() != "" ? entity->getName() : entity->getID().toString(); - qCDebug(entities) << "sim ownership for" << itemName << "is now" << senderID; - } - } + // if (wantTerseEditLogging()) { + // if (properties.simulationOwnerChanged()) { + // qCDebug(entities) << "sim ownership for" << entity->getDebugName() << "is now" << senderID; + // } + // } } // else client accepts what the server says @@ -764,9 +763,7 @@ int EntityTree::processEditPacketData(NLPacket& packet, const unsigned char* edi if (wantTerseEditLogging()) { QList changedProperties = properties.listChangedProperties(); fixupTerseEditLogging(properties, changedProperties); - QString itemName = - existingEntity->getName() != "" ? existingEntity->getName() : entityItemID.toString(); - qCDebug(entities) << "edit" << itemName << changedProperties; + qCDebug(entities) << "edit" << existingEntity->getDebugName() << changedProperties; } endLogging = usecTimestampNow(); From f07d5d9d3f290f161171d33f659e3d02ee4ffb6e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 11 Nov 2015 11:32:12 -0800 Subject: [PATCH 22/61] show network and physics status on boxes and spheres --- libraries/entities-renderer/src/RenderableEntityItem.cpp | 2 +- libraries/entities-renderer/src/RenderableEntityItem.h | 8 ++++++-- .../entities-renderer/src/RenderableModelEntityItem.cpp | 4 ++-- .../src/RenderableParticleEffectEntityItem.cpp | 2 +- .../entities-renderer/src/RenderablePolyVoxEntityItem.cpp | 2 +- .../entities-renderer/src/RenderableZoneEntityItem.cpp | 4 ++-- 6 files changed, 13 insertions(+), 9 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index ea6f004b30..5013f4d6f8 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -41,7 +41,7 @@ namespace render { } } -void makeEntityItemStatusGetters(EntityItem* entity, render::Item::Status::Getters& statusGetters) { +void makeEntityItemStatusGetters(EntityItemPointer entity, render::Item::Status::Getters& statusGetters) { statusGetters.push_back([entity] () -> render::Item::Status::Value { quint64 delta = usecTimestampNow() - entity->getLastEditedFromRemote(); const float WAIT_THRESHOLD_INV = 1.0f / (0.2f * USECS_PER_SECOND); diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index 4da8ff1b4c..ce5f2d49fa 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -25,6 +25,8 @@ enum class RenderItemStatusIcon { NONE = 255 }; +void makeEntityItemStatusGetters(EntityItemPointer entity, render::Item::Status::Getters& statusGetters); + class RenderableEntityItemProxy { public: @@ -50,6 +52,10 @@ public: auto renderData = std::make_shared(self); auto renderPayload = std::make_shared(renderData); + render::Item::Status::Getters statusGetters; + makeEntityItemStatusGetters(self, statusGetters); + renderPayload->addStatusGetters(statusGetters); + pendingChanges.resetItem(_myItem, renderPayload); return true; @@ -72,6 +78,4 @@ private: \ SimpleRenderableEntityItem _renderHelper; -void makeEntityItemStatusGetters(EntityItem* entity, render::Item::Status::Getters& statusGetters); - #endif // hifi_RenderableEntityItem_h diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index a9cb19e2ff..f1be8611e1 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -192,7 +192,7 @@ bool RenderableModelEntityItem::addToScene(EntityItemPointer self, std::shared_p if (_model) { render::Item::Status::Getters statusGetters; - makeEntityItemStatusGetters(this, statusGetters); + makeEntityItemStatusGetters(shared_from_this(), statusGetters); // note: we don't care if the model fails to add items, we always added our meta item and therefore we return // true so that the system knows our meta item is in the scene! @@ -236,7 +236,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { _model->removeFromScene(scene, pendingChanges); render::Item::Status::Getters statusGetters; - makeEntityItemStatusGetters(this, statusGetters); + makeEntityItemStatusGetters(shared_from_this(), statusGetters); _model->addToScene(scene, pendingChanges, statusGetters, _showCollisionHull); scene->enqueuePendingChanges(pendingChanges); diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index ecb16424d6..05fca343fd 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -140,7 +140,7 @@ bool RenderableParticleEffectEntityItem::addToScene(EntityItemPointer self, auto renderData = ParticlePayload::Pointer(particlePayload); auto renderPayload = render::PayloadPointer(new ParticlePayload::Payload(renderData)); render::Item::Status::Getters statusGetters; - makeEntityItemStatusGetters(this, statusGetters); + makeEntityItemStatusGetters(shared_from_this(), statusGetters); renderPayload->addStatusGetters(statusGetters); pendingChanges.resetItem(_renderItemId, renderPayload); _scene = scene; diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index a4e20bfcf9..2e8b8920ce 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -550,7 +550,7 @@ bool RenderablePolyVoxEntityItem::addToScene(EntityItemPointer self, auto renderPayload = std::make_shared(renderData); render::Item::Status::Getters statusGetters; - makeEntityItemStatusGetters(this, statusGetters); + makeEntityItemStatusGetters(shared_from_this(), statusGetters); renderPayload->addStatusGetters(statusGetters); pendingChanges.resetItem(_myItem, renderPayload); diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index 8b2a2d33df..b7b91c9b3a 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -115,7 +115,7 @@ void RenderableZoneEntityItem::render(RenderArgs* args) { render::PendingChanges pendingChanges; _model->removeFromScene(scene, pendingChanges); render::Item::Status::Getters statusGetters; - makeEntityItemStatusGetters(this, statusGetters); + makeEntityItemStatusGetters(shared_from_this(), statusGetters); _model->addToScene(scene, pendingChanges, false); scene->enqueuePendingChanges(pendingChanges); @@ -209,7 +209,7 @@ bool RenderableZoneEntityItem::addToScene(EntityItemPointer self, std::shared_pt auto renderPayload = std::make_shared(renderData); render::Item::Status::Getters statusGetters; - makeEntityItemStatusGetters(this, statusGetters); + makeEntityItemStatusGetters(shared_from_this(), statusGetters); renderPayload->addStatusGetters(statusGetters); pendingChanges.resetItem(_myMetaItem, renderPayload); From 07f3d8eca04aa1c82a990a32ea7f1520d9fa3d55 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 11 Nov 2015 16:03:08 -0800 Subject: [PATCH 23/61] more debugging prints --- .../entities/src/EntityActionInterface.cpp | 21 ++++++++++ .../entities/src/EntityActionInterface.h | 2 + libraries/entities/src/EntityItem.cpp | 38 ++++++++++--------- libraries/entities/src/EntityTree.cpp | 20 ++++------ libraries/entities/src/SimulationOwner.cpp | 2 +- 5 files changed, 52 insertions(+), 31 deletions(-) diff --git a/libraries/entities/src/EntityActionInterface.cpp b/libraries/entities/src/EntityActionInterface.cpp index 549aacbd0a..ce9a93a6ac 100644 --- a/libraries/entities/src/EntityActionInterface.cpp +++ b/libraries/entities/src/EntityActionInterface.cpp @@ -304,3 +304,24 @@ QDataStream& operator>>(QDataStream& stream, EntityActionType& entityActionType) entityActionType = (EntityActionType)actionTypeAsInt; return stream; } + +QString serializedActionsToDebugString(QByteArray data) { + if (data.size() == 0) { + return QString(); + } + QVector serializedActions; + QDataStream serializedActionsStream(data); + serializedActionsStream >> serializedActions; + + QString result; + foreach(QByteArray serializedAction, serializedActions) { + QDataStream serializedActionStream(serializedAction); + EntityActionType actionType; + QUuid actionID; + serializedActionStream >> actionType; + serializedActionStream >> actionID; + result += EntityActionInterface::actionTypeToString(actionType) + "-" + actionID.toString() + " "; + } + + return result; +} diff --git a/libraries/entities/src/EntityActionInterface.h b/libraries/entities/src/EntityActionInterface.h index b257df3325..01292e3840 100644 --- a/libraries/entities/src/EntityActionInterface.h +++ b/libraries/entities/src/EntityActionInterface.h @@ -89,4 +89,6 @@ typedef std::shared_ptr EntityActionPointer; QDataStream& operator<<(QDataStream& stream, const EntityActionType& entityActionType); QDataStream& operator>>(QDataStream& stream, EntityActionType& entityActionType); +QString serializedActionsToDebugString(QByteArray data); + #endif // hifi_EntityActionInterface_h diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 8aa2bdb5d3..807186a304 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -630,11 +630,11 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef dataAt += bytes; bytesRead += bytes; + if (wantTerseEditLogging() && _simulationOwner != newSimOwner) { + qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << newSimOwner; + } if (_simulationOwner.set(newSimOwner)) { _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; - if (wantTerseEditLogging()) { - qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << newSimOwner; - } } } { // When we own the simulation we don't accept updates to the entity's transform/velocities @@ -740,7 +740,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef // this "new" data is actually slightly out of date. We calculate the time we need to skip forward and // use our simulation helper routine to get a best estimate of where the entity should be. float skipTimeForward = (float)(now - lastSimulatedFromBufferAdjusted) / (float)(USECS_PER_SECOND); - + // we want to extrapolate the motion forward to compensate for packet travel time, but // we don't want the side effect of flag setting. simulateKinematicMotion(skipTimeForward, false); @@ -748,7 +748,6 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef if (overwriteLocalData) { if (!_simulationOwner.matchesValidID(myNodeID)) { - _lastSimulated = now; } } @@ -1500,33 +1499,36 @@ void EntityItem::updateCreated(uint64_t value) { } void EntityItem::setSimulationOwner(const QUuid& id, quint8 priority) { - if (_simulationOwner.set(id, priority)) { - if (wantTerseEditLogging()) { - qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << id; - } + if (wantTerseEditLogging() && (id != _simulationOwner.getID() || priority != _simulationOwner.getPriority())) { + qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << id << priority; } + _simulationOwner.set(id, priority); } void EntityItem::setSimulationOwner(const SimulationOwner& owner) { - if (_simulationOwner.set(owner)) { - if (wantTerseEditLogging()) { - qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << owner; - } + if (wantTerseEditLogging() && _simulationOwner != owner) { + qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << owner; } + + _simulationOwner.set(owner); } void EntityItem::updateSimulatorID(const QUuid& value) { + if (wantTerseEditLogging() && _simulationOwner.getID() != value) { + qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << value; + } + if (_simulationOwner.setID(value)) { _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; - if (wantTerseEditLogging()) { - qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << value; - } } } void EntityItem::clearSimulationOwnership() { + if (wantTerseEditLogging() && !_simulationOwner.isNull()) { + qCDebug(entities) << "sim ownership for" << getDebugName() << "is now null"; + } + _simulationOwner.clear(); - qCDebug(entities) << "sim ownership for" << getDebugName() << "is now null"; // don't bother setting the DIRTY_SIMULATOR_ID flag because clearSimulationOwnership() // is only ever called entity-server-side and the flags are only used client-side //_dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; @@ -1669,7 +1671,7 @@ void EntityItem::deserializeActionsInternal() { return; } - EntityTreePointer entityTree = _element ? _element->getTree() : nullptr; + EntityTreePointer entityTree = getTree(); assert(entityTree); EntitySimulation* simulation = entityTree ? entityTree->getSimulation() : nullptr; assert(simulation); diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 179e68ea29..de97af988d 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -197,13 +197,11 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI properties.setVelocityChanged(false); properties.setAngularVelocityChanged(false); properties.setAccelerationChanged(false); - } - // if (wantTerseEditLogging()) { - // if (properties.simulationOwnerChanged()) { - // qCDebug(entities) << "sim ownership for" << entity->getDebugName() << "is now" << senderID; - // } - // } + if (wantTerseEditLogging()) { + qCDebug(entities) << senderNode->getUUID() << "physical edits suppressed"; + } + } } // else client accepts what the server says @@ -666,10 +664,7 @@ void EntityTree::fixupTerseEditLogging(EntityItemProperties& properties, QList= 0) { QByteArray value = properties.getActionData(); - QString changeHint = "0"; - if (value.size() > 0) { - changeHint = "+"; - } + QString changeHint = serializedActionsToDebugString(value); changedProperties[index] = QString("actionData:") + changeHint; } } @@ -763,7 +758,8 @@ int EntityTree::processEditPacketData(NLPacket& packet, const unsigned char* edi if (wantTerseEditLogging()) { QList changedProperties = properties.listChangedProperties(); fixupTerseEditLogging(properties, changedProperties); - qCDebug(entities) << "edit" << existingEntity->getDebugName() << changedProperties; + qCDebug(entities) << senderNode->getUUID() << "edit" << + existingEntity->getDebugName() << changedProperties; } endLogging = usecTimestampNow(); @@ -793,7 +789,7 @@ int EntityTree::processEditPacketData(NLPacket& packet, const unsigned char* edi if (wantTerseEditLogging()) { QList changedProperties = properties.listChangedProperties(); fixupTerseEditLogging(properties, changedProperties); - qCDebug(entities) << "add" << entityItemID << changedProperties; + qCDebug(entities) << senderNode->getUUID() << "add" << entityItemID << changedProperties; } endLogging = usecTimestampNow(); diff --git a/libraries/entities/src/SimulationOwner.cpp b/libraries/entities/src/SimulationOwner.cpp index d6957873e2..24f6784954 100644 --- a/libraries/entities/src/SimulationOwner.cpp +++ b/libraries/entities/src/SimulationOwner.cpp @@ -157,7 +157,7 @@ void SimulationOwner::test() { } bool SimulationOwner::operator!=(const SimulationOwner& other) { - return (_id != other._id && _priority != other._priority); + return (_id != other._id || _priority != other._priority); } SimulationOwner& SimulationOwner::operator=(const SimulationOwner& other) { From 715a46ee82c2d61ba94fa8b1fc1aef29adb70232 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 11 Nov 2015 16:35:04 -0800 Subject: [PATCH 24/61] show actions in status icons --- interface/resources/icons/statusIconAtlas.svg | 1 + .../src/RenderableEntityItem.cpp | 9 ++++ .../src/RenderableEntityItem.h | 1 + libraries/render/src/render/DrawStatus.cpp | 41 +++++++++++++++---- libraries/render/src/render/DrawStatus.h | 3 +- libraries/render/src/render/Scene.cpp | 23 ++++------- libraries/render/src/render/Scene.h | 6 ++- .../render/src/render/drawItemStatus.slv | 19 +++++++-- 8 files changed, 72 insertions(+), 31 deletions(-) diff --git a/interface/resources/icons/statusIconAtlas.svg b/interface/resources/icons/statusIconAtlas.svg index 3e15da10cb..72f9bc4af7 100644 --- a/interface/resources/icons/statusIconAtlas.svg +++ b/interface/resources/icons/statusIconAtlas.svg @@ -27,4 +27,5 @@ c-3.9-1.9-7.8-3.7-11.7-5.6c-4-2-4.6-8.1-1.1-10.8c2-1.5,2.4-3.7,2.1-5.9c-0.2-1.8-1-3.5-1.2-5.3c-0.6-6-5.2-10.2-11.1-10.1 c-5.9,0.1-10.4,4.8-10.6,10.9c-0.1,1.4-0.4,2.8-0.9,4.1c-0.6,1.9,0.1,4.9,1.7,6.3c3.8,3.1,3.1,9-1.4,11.2c-3.6,1.7-7.2,3.4-10.8,5.2 c-3.4,1.6-3.6,2.5-0.8,5.1C336.2,80.6,343.8,83.9,353.7,83.9z"/> + diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index 5013f4d6f8..5504268dce 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -88,4 +88,13 @@ void makeEntityItemStatusGetters(EntityItemPointer entity, render::Item::Status: return render::Item::Status::Value(0.0f, render::Item::Status::Value::BLUE, (unsigned char)RenderItemStatusIcon::SIMULATION_OWNER); }); + + statusGetters.push_back([entity] () -> render::Item::Status::Value { + if (entity->hasActions()) { + return render::Item::Status::Value(1.0f, render::Item::Status::Value::GREEN, + (unsigned char)RenderItemStatusIcon::HAS_ACTIONS); + } + return render::Item::Status::Value(0.0f, render::Item::Status::Value::GREEN, + (unsigned char)RenderItemStatusIcon::HAS_ACTIONS); + }); } diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index ce5f2d49fa..212b71759f 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -22,6 +22,7 @@ enum class RenderItemStatusIcon { PACKET_SENT = 1, PACKET_RECEIVED = 2, SIMULATION_OWNER = 3, + HAS_ACTIONS = 4, NONE = 255 }; diff --git a/libraries/render/src/render/DrawStatus.cpp b/libraries/render/src/render/DrawStatus.cpp index 7b344ae63e..3171b8160c 100644 --- a/libraries/render/src/render/DrawStatus.cpp +++ b/libraries/render/src/render/DrawStatus.cpp @@ -68,7 +68,8 @@ const gpu::PipelinePointer DrawStatus::getDrawItemStatusPipeline() { _drawItemStatusPosLoc = program->getUniforms().findLocation("inBoundPos"); _drawItemStatusDimLoc = program->getUniforms().findLocation("inBoundDim"); - _drawItemStatusValueLoc = program->getUniforms().findLocation("inStatus"); + _drawItemStatusValue0Loc = program->getUniforms().findLocation("inStatus0"); + _drawItemStatusValue1Loc = program->getUniforms().findLocation("inStatus1"); auto state = std::make_shared(); @@ -98,6 +99,8 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex assert(renderContext->args->_viewFrustum); RenderArgs* args = renderContext->args; auto& scene = sceneContext->_scene; + const int NUM_STATUS_VEC4_PER_ITEM = 2; + const int VEC4_LENGTH = 4; // FIrst thing, we collect the bound and the status for all the items we want to render int nbItems = 0; @@ -109,8 +112,8 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex _itemStatus = std::make_shared();; } - _itemBounds->resize((inItems.size() * sizeof(AABox))); - _itemStatus->resize((inItems.size() * sizeof(glm::vec4))); + _itemBounds->resize((inItems.size() * sizeof(AABox))); + _itemStatus->resize((inItems.size() * NUM_STATUS_VEC4_PER_ITEM * sizeof(glm::vec4))); AABox* itemAABox = reinterpret_cast (_itemBounds->editData()); glm::ivec4* itemStatus = reinterpret_cast (_itemStatus->editData()); for (auto& item : inItems) { @@ -121,11 +124,31 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex (*itemAABox).setBox(item.bounds.getCorner(), 0.1f); } auto& itemScene = scene->getItem(item.id); - (*itemStatus) = itemScene.getStatusPackedValues(); + + auto itemStatusPointer = itemScene.getStatus(); + if (itemStatusPointer) { + // Query the current status values, this is where the statusGetter lambda get called + auto&& currentStatusValues = itemStatusPointer->getCurrentValues(); + int valueNum = 0; + for (int vec4Num = 0; vec4Num < NUM_STATUS_VEC4_PER_ITEM; vec4Num++) { + (*itemStatus) = glm::ivec4(Item::Status::Value::INVALID.getPackedData()); + for (int component = 0; component < VEC4_LENGTH; component++) { + valueNum = vec4Num * VEC4_LENGTH + component; + if (valueNum < (int)currentStatusValues.size()) { + (*itemStatus)[component] = currentStatusValues[valueNum].getPackedData(); + } + } + itemStatus++; + } + } else { + (*itemStatus) = glm::ivec4(Item::Status::Value::INVALID.getPackedData()); + itemStatus++; + (*itemStatus) = glm::ivec4(Item::Status::Value::INVALID.getPackedData()); + itemStatus++; + } nbItems++; - itemAABox++; - itemStatus++; + itemAABox++; } } } @@ -170,9 +193,9 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex for (int i = 0; i < nbItems; i++) { batch._glUniform3fv(_drawItemStatusPosLoc, 1, (const float*) (itemAABox + i)); batch._glUniform3fv(_drawItemStatusDimLoc, 1, ((const float*) (itemAABox + i)) + VEC3_ADRESS_OFFSET); - batch._glUniform4iv(_drawItemStatusValueLoc, 1, (const int*) (itemStatus + i)); - - batch.draw(gpu::TRIANGLES, 24, 0); + batch._glUniform4iv(_drawItemStatusValue0Loc, 1, (const int*)(itemStatus + NUM_STATUS_VEC4_PER_ITEM * i)); + batch._glUniform4iv(_drawItemStatusValue1Loc, 1, (const int*)(itemStatus + NUM_STATUS_VEC4_PER_ITEM * i + 1)); + batch.draw(gpu::TRIANGLES, 24 * NUM_STATUS_VEC4_PER_ITEM, 0); } } batch.setResourceTexture(0, 0); diff --git a/libraries/render/src/render/DrawStatus.h b/libraries/render/src/render/DrawStatus.h index bb9cb07e4b..83be3112e0 100644 --- a/libraries/render/src/render/DrawStatus.h +++ b/libraries/render/src/render/DrawStatus.h @@ -21,7 +21,8 @@ namespace render { int _drawItemBoundDimLoc = -1; int _drawItemStatusPosLoc = -1; int _drawItemStatusDimLoc = -1; - int _drawItemStatusValueLoc = -1; + int _drawItemStatusValue0Loc = -1; + int _drawItemStatusValue1Loc = -1; gpu::Stream::FormatPointer _drawItemFormat; gpu::PipelinePointer _drawItemBoundsPipeline; diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index 2081d5267f..18cf1d8335 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -78,14 +78,14 @@ void Item::Status::Value::setIcon(unsigned char icon) { _icon = icon; } -void Item::Status::getPackedValues(glm::ivec4& values) const { - for (unsigned int i = 0; i < (unsigned int)values.length(); i++) { - if (i < _values.size()) { - values[i] = _values[i]().getPackedData(); - } else { - values[i] = Value::INVALID.getPackedData(); - } +Item::Status::Values Item::Status::getCurrentValues() const { + Values currentValues(_values.size()); + auto currentValue = currentValues.begin(); + for (auto& getter : _values) { + (*currentValue) = getter(); + currentValue++; } + return currentValues; } void Item::PayloadInterface::addStatusGetter(const Status::Getter& getter) { @@ -113,15 +113,6 @@ void Item::resetPayload(const PayloadPointer& payload) { } } -glm::ivec4 Item::getStatusPackedValues() const { - glm::ivec4 values(Status::Value::INVALID.getPackedData()); - auto& status = getStatus(); - if (status) { - status->getPackedValues(values); - }; - return values; -} - void PendingChanges::resetItem(ItemID id, const PayloadPointer& payload) { _resetItems.push_back(id); _resetPayloads.push_back(payload); diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 7176e5753e..6ddd60cce8 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -241,7 +241,10 @@ public: void addGetter(const Getter& getter) { _values.push_back(getter); } - void getPackedValues(glm::ivec4& values) const; + size_t getNumValues() const { return _values.size(); } + + using Values = std::vector ; + Values getCurrentValues() const; }; typedef std::shared_ptr StatusPointer; @@ -305,7 +308,6 @@ public: // Access the status const StatusPointer& getStatus() const { return _payload->getStatus(); } - glm::ivec4 getStatusPackedValues() const; protected: PayloadPointer _payload; diff --git a/libraries/render/src/render/drawItemStatus.slv b/libraries/render/src/render/drawItemStatus.slv index 8c4f0724d5..9974146916 100644 --- a/libraries/render/src/render/drawItemStatus.slv +++ b/libraries/render/src/render/drawItemStatus.slv @@ -21,7 +21,8 @@ out vec3 varTexcoord; uniform vec3 inBoundPos; uniform vec3 inBoundDim; -uniform ivec4 inStatus; +uniform ivec4 inStatus0; +uniform ivec4 inStatus1; vec3 paintRainbow(float normalizedHue) { float v = normalizedHue * 6.f; @@ -44,6 +45,17 @@ vec3 paintRainbow(float normalizedHue) { } } +const int INVALID_STATUS = 0xFFFFFFFF; + +int getIconStatus(int icon) { + if (icon < 4) { + return inStatus0[icon]; + } else if (icon < 8) { + return inStatus1[icon - 4]; + } + return INVALID_STATUS; +} + vec3 unpackStatus(int v) { return vec3(clamp(float(int((v >> 0) & 0xFFFF) - 32727) / 32727.0, -1.0, 1.0), clamp(float(uint((v >> 16) & 0xFF)) / 255.0, 0.0, 1.0), @@ -71,9 +83,10 @@ void main(void) { // Which icon are we dealing with ? int iconNum = gl_VertexID / NUM_VERTICES; + int packedIconStatus = getIconStatus(iconNum); // if invalid, just kill - if (inStatus[iconNum] == 0xFFFFFFFF) { + if (packedIconStatus == INVALID_STATUS) { gl_Position = anchorPoint; varColor = vec4(1.0); return; @@ -84,7 +97,7 @@ void main(void) { vec4 quadPos = UNIT_QUAD[twoTriID]; // unpack to get x and y satus - vec3 iconStatus = unpackStatus(inStatus[iconNum]); + vec3 iconStatus = unpackStatus(packedIconStatus); // Use the status for showing a color varColor = vec4(paintRainbow(abs(iconStatus.y)), 1.0); From be8674820022dca2efdeaa82fd0addcefe722919 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 11 Nov 2015 16:38:28 -0800 Subject: [PATCH 25/61] oops --- assignment-client/src/octree/OctreeSendThread.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 96646d9e39..ffcab74b87 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -571,9 +571,9 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus } if (somethingToSend && _myServer->wantsVerboseDebug()) { - qCDebug(otree) << "Hit PPS Limit, packetsSentThisInterval =" << packetsSentThisInterval - << " maxPacketsPerInterval = " << maxPacketsPerInterval - << " clientMaxPacketsPerInterval = " << clientMaxPacketsPerInterval; + qCDebug(octree) << "Hit PPS Limit, packetsSentThisInterval =" << packetsSentThisInterval + << " maxPacketsPerInterval = " << maxPacketsPerInterval + << " clientMaxPacketsPerInterval = " << clientMaxPacketsPerInterval; } // Here's where we can/should allow the server to send other data... From a16a477134380d32e10d7dd289dc488278b140e3 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 11 Nov 2015 16:51:55 -0800 Subject: [PATCH 26/61] fix warning --- libraries/render/src/render/drawItemStatus.slv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render/src/render/drawItemStatus.slv b/libraries/render/src/render/drawItemStatus.slv index 9974146916..f078e3fd65 100644 --- a/libraries/render/src/render/drawItemStatus.slv +++ b/libraries/render/src/render/drawItemStatus.slv @@ -45,7 +45,7 @@ vec3 paintRainbow(float normalizedHue) { } } -const int INVALID_STATUS = 0xFFFFFFFF; +const int INVALID_STATUS = int(0xFFFFFFFF); int getIconStatus(int icon) { if (icon < 4) { From 83d5c9cf4a367e871dd3445033e23ac15ee32133 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 11 Nov 2015 18:54:07 -0800 Subject: [PATCH 27/61] arrange status icons in two rows of 4 each --- libraries/render/src/render/DrawStatus.cpp | 1 + .../render/src/render/drawItemStatus.slv | 32 +++++++++++++------ 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/libraries/render/src/render/DrawStatus.cpp b/libraries/render/src/render/DrawStatus.cpp index 3171b8160c..c7a54b18d0 100644 --- a/libraries/render/src/render/DrawStatus.cpp +++ b/libraries/render/src/render/DrawStatus.cpp @@ -163,6 +163,7 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex Transform viewMat; args->_viewFrustum->evalProjectionMatrix(projMat); args->_viewFrustum->evalViewTransform(viewMat); + batch.setViewportTransform(args->_viewport); batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); diff --git a/libraries/render/src/render/drawItemStatus.slv b/libraries/render/src/render/drawItemStatus.slv index f078e3fd65..cb4ae7ebd2 100644 --- a/libraries/render/src/render/drawItemStatus.slv +++ b/libraries/render/src/render/drawItemStatus.slv @@ -46,12 +46,14 @@ vec3 paintRainbow(float normalizedHue) { } const int INVALID_STATUS = int(0xFFFFFFFF); +const int MAX_NUM_ICONS = 8; +const int ICONS_PER_ROW = 4; int getIconStatus(int icon) { - if (icon < 4) { + if (icon < ICONS_PER_ROW) { return inStatus0[icon]; - } else if (icon < 8) { - return inStatus1[icon - 4]; + } else if (icon < MAX_NUM_ICONS) { + return inStatus1[icon - ICONS_PER_ROW]; } return INVALID_STATUS; } @@ -63,10 +65,8 @@ vec3 unpackStatus(int v) { } void main(void) { - const vec2 ICON_PIXEL_SIZE = vec2(20, 20); - const vec2 MARGIN_PIXEL_SIZE = vec2(2, 2); - const int NUM_VERTICES = 6; - const vec4 UNIT_QUAD[NUM_VERTICES] = vec4[NUM_VERTICES]( + const int NUM_VERTICES_PER_ICON = 6; + const vec4 UNIT_QUAD[NUM_VERTICES_PER_ICON] = vec4[NUM_VERTICES_PER_ICON]( vec4(-1.0, -1.0, 0.0, 1.0), vec4(1.0, -1.0, 0.0, 1.0), vec4(-1.0, 1.0, 0.0, 1.0), @@ -75,6 +75,17 @@ void main(void) { vec4(1.0, 1.0, 0.0, 1.0) ); + const vec2 ICON_PIXEL_SIZE = vec2(20, 20); + const vec2 MARGIN_PIXEL_SIZE = vec2(2, 2); + const vec2 ICON_GRID_SLOTS[MAX_NUM_ICONS] = vec2[MAX_NUM_ICONS](vec2(-1.5, 0.5), + vec2(-0.5, 0.5), + vec2(0.5, 0.5), + vec2(1.5, 0.5), + vec2(-1.5,-0.5), + vec2(-0.5,-0.5), + vec2(0.5, -0.5), + vec2(1.5, -0.5)); + // anchor point in clip space vec4 anchorPoint = vec4(inBoundPos, 1.0) + vec4(inBoundDim, 0.0) * vec4(0.5, 0.5, 0.5, 0.0); TransformCamera cam = getTransformCamera(); @@ -82,7 +93,7 @@ void main(void) { <$transformModelToClipPos(cam, obj, anchorPoint, anchorPoint)$> // Which icon are we dealing with ? - int iconNum = gl_VertexID / NUM_VERTICES; + int iconNum = gl_VertexID / NUM_VERTICES_PER_ICON; int packedIconStatus = getIconStatus(iconNum); // if invalid, just kill @@ -93,7 +104,7 @@ void main(void) { } // Which quad vertex pos? - int twoTriID = gl_VertexID - iconNum * NUM_VERTICES; + int twoTriID = gl_VertexID - iconNum * NUM_VERTICES_PER_ICON; vec4 quadPos = UNIT_QUAD[twoTriID]; // unpack to get x and y satus @@ -110,7 +121,8 @@ void main(void) { iconScale = max(vec2(0, 0), (iconScale * iconStatus.x)); //Offset icon to the right based on the iconNum - vec2 offset = vec2(iconNum * (ICON_PIXEL_SIZE.x + MARGIN_PIXEL_SIZE.x), 0); + vec2 gridOffset = ICON_GRID_SLOTS[iconNum]; + vec2 offset = gridOffset * (ICON_PIXEL_SIZE + MARGIN_PIXEL_SIZE); // Final position in pixel space vec2 quadPixelPos = offset.xy + quadPos.xy * 0.5 * iconScale; From 93da3ed5bdc282b719983286bbcb5e8921de38ae Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 12 Nov 2015 11:03:34 -0800 Subject: [PATCH 28/61] if our simulation-bid priority matches the remote one, don't bid. --- libraries/physics/src/EntityMotionState.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 9be6dd38b1..21b7187063 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -116,8 +116,8 @@ bool EntityMotionState::handleEasyChanges(uint32_t flags, PhysicsEngine* engine) _outgoingPriority = NO_PRORITY; } else { _nextOwnershipBid = usecTimestampNow() + USECS_BETWEEN_OWNERSHIP_BIDS; - if (engine->getSessionID() == _entity->getSimulatorID() || _entity->getSimulationPriority() > _outgoingPriority) { - // we own the simulation or our priority looses to remote + if (engine->getSessionID() == _entity->getSimulatorID() || _entity->getSimulationPriority() >= _outgoingPriority) { + // we own the simulation or our priority looses to (or ties with) remote _outgoingPriority = NO_PRORITY; } } @@ -379,7 +379,7 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationStep, const QUuid& s // we don't own the simulation, but maybe we should... if (_outgoingPriority != NO_PRORITY) { if (_outgoingPriority < _entity->getSimulationPriority()) { - // our priority looses to remote, so we don't bother to bid + // our priority loses to remote, so we don't bother to bid _outgoingPriority = NO_PRORITY; return false; } From a366633f843e45178ceeae1f3cf74bc3c4fae2a7 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 12 Nov 2015 11:03:44 -0800 Subject: [PATCH 29/61] cleanups --- libraries/render/src/render/DrawStatus.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/libraries/render/src/render/DrawStatus.cpp b/libraries/render/src/render/DrawStatus.cpp index c7a54b18d0..5e8fd74e5f 100644 --- a/libraries/render/src/render/DrawStatus.cpp +++ b/libraries/render/src/render/DrawStatus.cpp @@ -87,20 +87,22 @@ const gpu::PipelinePointer DrawStatus::getDrawItemStatusPipeline() { } void DrawStatus::setStatusIconMap(const gpu::TexturePointer& map) { - _statusIconMap = map; + _statusIconMap = map; } const gpu::TexturePointer DrawStatus::getStatusIconMap() const { - return _statusIconMap; + return _statusIconMap; } -void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems) { +void DrawStatus::run(const SceneContextPointer& sceneContext, + const RenderContextPointer& renderContext, + const ItemIDsBounds& inItems) { assert(renderContext->args); assert(renderContext->args->_viewFrustum); RenderArgs* args = renderContext->args; auto& scene = sceneContext->_scene; - const int NUM_STATUS_VEC4_PER_ITEM = 2; - const int VEC4_LENGTH = 4; + const int NUM_STATUS_VEC4_PER_ITEM = 2; + const int VEC4_LENGTH = 4; // FIrst thing, we collect the bound and the status for all the items we want to render int nbItems = 0; @@ -112,8 +114,8 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex _itemStatus = std::make_shared();; } - _itemBounds->resize((inItems.size() * sizeof(AABox))); - _itemStatus->resize((inItems.size() * NUM_STATUS_VEC4_PER_ITEM * sizeof(glm::vec4))); + _itemBounds->resize((inItems.size() * sizeof(AABox))); + _itemStatus->resize((inItems.size() * NUM_STATUS_VEC4_PER_ITEM * sizeof(glm::vec4))); AABox* itemAABox = reinterpret_cast (_itemBounds->editData()); glm::ivec4* itemStatus = reinterpret_cast (_itemStatus->editData()); for (auto& item : inItems) { @@ -148,7 +150,7 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex } nbItems++; - itemAABox++; + itemAABox++; } } } From 2e635bd93638413fe9d66d14d7bb0bd576f1a85b Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 12 Nov 2015 11:14:25 -0800 Subject: [PATCH 30/61] cleanups --- libraries/physics/src/EntityMotionState.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 21b7187063..bd744c8be3 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -535,7 +535,7 @@ void EntityMotionState::clearIncomingDirtyFlags() { } } -// virtual +// virtual quint8 EntityMotionState::getSimulationPriority() const { if (_entity) { return _entity->getSimulationPriority(); From 288ee0e9e865a6eef1d3dcc4ac5133bdeadebaf4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 12 Nov 2015 11:39:32 -0800 Subject: [PATCH 31/61] add a NodeDisconnect packet --- libraries/networking/src/udt/PacketHeaders.cpp | 1 + libraries/networking/src/udt/PacketHeaders.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 24034ff9b3..669556c74a 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -93,6 +93,7 @@ QString nameForPacketType(PacketType packetType) { PACKET_TYPE_NAME_LOOKUP(PacketType::EntityAdd); PACKET_TYPE_NAME_LOOKUP(PacketType::EntityEdit); PACKET_TYPE_NAME_LOOKUP(PacketType::DomainServerConnectionToken); + PACKET_TYPE_NAME_LOOKUP(PacketType::NodeDisconnect) default: return QString("Type: ") + QString::number((int)packetType); } diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 82d905bf28..a77b2dab18 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -79,7 +79,8 @@ enum class PacketType : uint8_t { AssetUpload, AssetUploadReply, AssetGetInfo, - AssetGetInfoReply + AssetGetInfoReply, + NodeDisconnect }; const int NUM_BYTES_MD5_HASH = 16; From a8cd891e48f6b2a53aeeedfd6c9f34ee66a086d1 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 12 Nov 2015 14:19:23 -0800 Subject: [PATCH 32/61] adjust how the decision to send action changes over the wire is made --- interface/src/avatar/AvatarActionHold.cpp | 2 +- libraries/entities/src/EntityItem.cpp | 8 +++----- libraries/entities/src/EntityItem.h | 5 +++-- libraries/physics/src/EntityMotionState.cpp | 2 +- libraries/physics/src/ObjectActionOffset.cpp | 2 +- libraries/physics/src/ObjectActionSpring.cpp | 2 +- 6 files changed, 10 insertions(+), 11 deletions(-) diff --git a/interface/src/avatar/AvatarActionHold.cpp b/interface/src/avatar/AvatarActionHold.cpp index 866f444b32..0d86e79a2d 100644 --- a/interface/src/avatar/AvatarActionHold.cpp +++ b/interface/src/avatar/AvatarActionHold.cpp @@ -211,7 +211,7 @@ bool AvatarActionHold::updateArguments(QVariantMap arguments) { auto ownerEntity = _ownerEntity.lock(); if (ownerEntity) { - ownerEntity->setActionDataDirty(true); + ownerEntity->setActionDataNeedsUpdate(true); } }); activateBody(); diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 807186a304..ef39cf8063 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1740,8 +1740,6 @@ void EntityItem::deserializeActionsInternal() { } } - _actionDataDirty = true; - return; } @@ -1802,11 +1800,11 @@ void EntityItem::serializeActions(bool& success, QByteArray& result) const { } const QByteArray EntityItem::getActionDataInternal() const { - if (_actionDataDirty) { + if (_actionDataNeedsUpdate) { bool success; serializeActions(success, _allActionsDataCache); if (success) { - _actionDataDirty = false; + _actionDataNeedsUpdate = false; } } return _allActionsDataCache; @@ -1816,7 +1814,7 @@ const QByteArray EntityItem::getActionData() const { QByteArray result; assertUnlocked(); - if (_actionDataDirty) { + if (_actionDataNeedsUpdate) { withWriteLock([&] { getActionDataInternal(); result = _allActionsDataCache; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index b3c976c1ca..6e4f3ac2ca 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -408,7 +408,8 @@ public: QList getActionIDs() { return _objectActions.keys(); } QVariantMap getActionArguments(const QUuid& actionID) const; void deserializeActions(); - void setActionDataDirty(bool value) const { _actionDataDirty = value; } + void setActionDataNeedsUpdate(bool value) const { _actionDataNeedsUpdate = value; } + bool actionDataNeedsUpdate() const { return _actionDataNeedsUpdate; } bool shouldSuppressLocationEdits() const; void setSourceUUID(const QUuid& sourceUUID) { _sourceUUID = sourceUUID; } @@ -511,7 +512,7 @@ protected: // are used to keep track of and work around this situation. void checkWaitingToRemove(EntitySimulation* simulation = nullptr); mutable QSet _actionsToRemove; - mutable bool _actionDataDirty = false; + mutable bool _actionDataNeedsUpdate = false; // _previouslyDeletedActions is used to avoid an action being re-added due to server round-trip lag static quint64 _rememberDeletedActionTime; mutable QHash _previouslyDeletedActions; diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index bd744c8be3..841a41cb04 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -297,7 +297,7 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) { _serverPosition += dt * _serverVelocity; } - if (_serverActionData != _entity->getActionData()) { + if (_entity->actionDataNeedsUpdate()) { setOutgoingPriority(SCRIPT_EDIT_SIMULATION_PRIORITY); return true; } diff --git a/libraries/physics/src/ObjectActionOffset.cpp b/libraries/physics/src/ObjectActionOffset.cpp index 2cfd98497b..be2f5b40a0 100644 --- a/libraries/physics/src/ObjectActionOffset.cpp +++ b/libraries/physics/src/ObjectActionOffset.cpp @@ -129,7 +129,7 @@ bool ObjectActionOffset::updateArguments(QVariantMap arguments) { auto ownerEntity = _ownerEntity.lock(); if (ownerEntity) { - ownerEntity->setActionDataDirty(true); + ownerEntity->setActionDataNeedsUpdate(true); } }); activateBody(); diff --git a/libraries/physics/src/ObjectActionSpring.cpp b/libraries/physics/src/ObjectActionSpring.cpp index c1cd2db5ca..7289c88a8f 100644 --- a/libraries/physics/src/ObjectActionSpring.cpp +++ b/libraries/physics/src/ObjectActionSpring.cpp @@ -162,7 +162,7 @@ bool ObjectActionSpring::updateArguments(QVariantMap arguments) { auto ownerEntity = _ownerEntity.lock(); if (ownerEntity) { - ownerEntity->setActionDataDirty(true); + ownerEntity->setActionDataNeedsUpdate(true); } }); activateBody(); From 0a64242160e8d1b90c0573a4eed226951abaa423 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 12 Nov 2015 14:43:25 -0800 Subject: [PATCH 33/61] cleanup string grabbing for PacketType enum --- ice-server/src/IceServer.cpp | 3 +- .../networking/src/udt/PacketHeaders.cpp | 61 +------- libraries/networking/src/udt/PacketHeaders.h | 130 ++++++++++-------- libraries/octree/src/Octree.cpp | 4 +- 4 files changed, 78 insertions(+), 120 deletions(-) diff --git a/ice-server/src/IceServer.cpp b/ice-server/src/IceServer.cpp index a6a28caa23..f65ff4a8cf 100644 --- a/ice-server/src/IceServer.cpp +++ b/ice-server/src/IceServer.cpp @@ -55,8 +55,7 @@ bool IceServer::packetVersionMatch(const udt::Packet& packet) { if (headerVersion == versionForPacketType(headerType)) { return true; } else { - qDebug() << "Packet version mismatch for packet" << headerType - << "(" << nameForPacketType(headerType) << ") from" << packet.getSenderSockAddr(); + qDebug() << "Packet version mismatch for packet" << headerType << " from" << packet.getSenderSockAddr(); return false; } diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 669556c74a..b389d4d3df 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -14,6 +14,7 @@ #include #include +#include const QSet NON_VERIFIED_PACKETS = QSet() << PacketType::NodeJsonStats << PacketType::EntityQuery @@ -46,60 +47,6 @@ PacketVersion versionForPacketType(PacketType packetType) { } } -#define PACKET_TYPE_NAME_LOOKUP(x) case x: return QString(#x); - -QString nameForPacketType(PacketType packetType) { - switch (packetType) { - PACKET_TYPE_NAME_LOOKUP(PacketType::Unknown); - PACKET_TYPE_NAME_LOOKUP(PacketType::StunResponse); - PACKET_TYPE_NAME_LOOKUP(PacketType::DomainList); - PACKET_TYPE_NAME_LOOKUP(PacketType::Ping); - PACKET_TYPE_NAME_LOOKUP(PacketType::PingReply); - PACKET_TYPE_NAME_LOOKUP(PacketType::KillAvatar); - PACKET_TYPE_NAME_LOOKUP(PacketType::AvatarData); - PACKET_TYPE_NAME_LOOKUP(PacketType::InjectAudio); - PACKET_TYPE_NAME_LOOKUP(PacketType::MixedAudio); - PACKET_TYPE_NAME_LOOKUP(PacketType::MicrophoneAudioNoEcho); - PACKET_TYPE_NAME_LOOKUP(PacketType::MicrophoneAudioWithEcho); - PACKET_TYPE_NAME_LOOKUP(PacketType::BulkAvatarData); - PACKET_TYPE_NAME_LOOKUP(PacketType::SilentAudioFrame); - PACKET_TYPE_NAME_LOOKUP(PacketType::DomainListRequest); - PACKET_TYPE_NAME_LOOKUP(PacketType::RequestAssignment); - PACKET_TYPE_NAME_LOOKUP(PacketType::CreateAssignment); - PACKET_TYPE_NAME_LOOKUP(PacketType::DomainConnectionDenied); - PACKET_TYPE_NAME_LOOKUP(PacketType::MuteEnvironment); - PACKET_TYPE_NAME_LOOKUP(PacketType::AudioStreamStats); - PACKET_TYPE_NAME_LOOKUP(PacketType::OctreeStats); - PACKET_TYPE_NAME_LOOKUP(PacketType::Jurisdiction); - PACKET_TYPE_NAME_LOOKUP(PacketType::JurisdictionRequest); - PACKET_TYPE_NAME_LOOKUP(PacketType::AvatarIdentity); - PACKET_TYPE_NAME_LOOKUP(PacketType::AvatarBillboard); - PACKET_TYPE_NAME_LOOKUP(PacketType::DomainConnectRequest); - PACKET_TYPE_NAME_LOOKUP(PacketType::DomainServerRequireDTLS); - PACKET_TYPE_NAME_LOOKUP(PacketType::NodeJsonStats); - PACKET_TYPE_NAME_LOOKUP(PacketType::EntityQuery); - PACKET_TYPE_NAME_LOOKUP(PacketType::EntityData); - PACKET_TYPE_NAME_LOOKUP(PacketType::EntityErase); - PACKET_TYPE_NAME_LOOKUP(PacketType::OctreeDataNack); - PACKET_TYPE_NAME_LOOKUP(PacketType::StopNode); - PACKET_TYPE_NAME_LOOKUP(PacketType::AudioEnvironment); - PACKET_TYPE_NAME_LOOKUP(PacketType::EntityEditNack); - PACKET_TYPE_NAME_LOOKUP(PacketType::ICEServerHeartbeat); - PACKET_TYPE_NAME_LOOKUP(PacketType::DomainServerAddedNode); - PACKET_TYPE_NAME_LOOKUP(PacketType::ICEServerQuery); - PACKET_TYPE_NAME_LOOKUP(PacketType::ICEServerPeerInformation); - PACKET_TYPE_NAME_LOOKUP(PacketType::ICEPing); - PACKET_TYPE_NAME_LOOKUP(PacketType::ICEPingReply); - PACKET_TYPE_NAME_LOOKUP(PacketType::EntityAdd); - PACKET_TYPE_NAME_LOOKUP(PacketType::EntityEdit); - PACKET_TYPE_NAME_LOOKUP(PacketType::DomainServerConnectionToken); - PACKET_TYPE_NAME_LOOKUP(PacketType::NodeDisconnect) - default: - return QString("Type: ") + QString::number((int)packetType); - } - return QString("unexpected"); -} - uint qHash(const PacketType& key, uint seed) { // seems odd that Qt couldn't figure out this cast itself, but this fixes a compile error after switch to // strongly typed enum for PacketType @@ -107,6 +54,10 @@ uint qHash(const PacketType& key, uint seed) { } QDebug operator<<(QDebug debug, const PacketType& type) { - debug.nospace() << (uint8_t) type << " (" << qPrintable(nameForPacketType(type)) << ")"; + QMetaObject metaObject = PacketTypeEnum::staticMetaObject; + QMetaEnum metaEnum = metaObject.enumerator(metaObject.enumeratorOffset()); + QString typeName = metaEnum.valueToKey((int) type); + + debug.nospace().noquote() << (uint8_t) type << " (" << typeName << ")"; return debug.space(); } diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index a77b2dab18..147c001ba9 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -18,71 +18,80 @@ #include #include +#include #include #include -// If adding a new packet packetType, you can replace one marked usable or add at the end. -// If you want the name of the packet packetType to be available for debugging or logging, update nameForPacketType() as well -// This enum must hold 256 or fewer packet types (so the value is <= 255) since it is statically typed as a uint8_t -enum class PacketType : uint8_t { - Unknown, - StunResponse, - DomainList, - Ping, - PingReply, - KillAvatar, - AvatarData, - InjectAudio, - MixedAudio, - MicrophoneAudioNoEcho, - MicrophoneAudioWithEcho, - BulkAvatarData, - SilentAudioFrame, - DomainListRequest, - RequestAssignment, - CreateAssignment, - DomainConnectionDenied, - MuteEnvironment, - AudioStreamStats, - DomainServerPathQuery, - DomainServerPathResponse, - DomainServerAddedNode, - ICEServerPeerInformation, - ICEServerQuery, - OctreeStats, - Jurisdiction, - JurisdictionRequest, - AssignmentClientStatus, - NoisyMute, - AvatarIdentity, - AvatarBillboard, - DomainConnectRequest, - DomainServerRequireDTLS, - NodeJsonStats, - OctreeDataNack, - StopNode, - AudioEnvironment, - EntityEditNack, - ICEServerHeartbeat, - ICEPing, - ICEPingReply, - EntityData, - EntityQuery, - EntityAdd, - EntityErase, - EntityEdit, - DomainServerConnectionToken, - DomainSettingsRequest, - DomainSettings, - AssetGet, - AssetGetReply, - AssetUpload, - AssetUploadReply, - AssetGetInfo, - AssetGetInfoReply, - NodeDisconnect +// The enums are inside this PacketTypeEnum for run-time conversion of enum value to string via +// Q_ENUMS, without requiring a macro that is called for each enum value. +class PacketTypeEnum { + Q_GADGET + Q_ENUMS(Value) +public: + // If adding a new packet packetType, you can replace one marked usable or add at the end. + // This enum must hold 256 or fewer packet types (so the value is <= 255) since it is statically typed as a uint8_t + enum class Value : uint8_t { + Unknown, + StunResponse, + DomainList, + Ping, + PingReply, + KillAvatar, + AvatarData, + InjectAudio, + MixedAudio, + MicrophoneAudioNoEcho, + MicrophoneAudioWithEcho, + BulkAvatarData, + SilentAudioFrame, + DomainListRequest, + RequestAssignment, + CreateAssignment, + DomainConnectionDenied, + MuteEnvironment, + AudioStreamStats, + DomainServerPathQuery, + DomainServerPathResponse, + DomainServerAddedNode, + ICEServerPeerInformation, + ICEServerQuery, + OctreeStats, + Jurisdiction, + JurisdictionRequest, + AssignmentClientStatus, + NoisyMute, + AvatarIdentity, + AvatarBillboard, + DomainConnectRequest, + DomainServerRequireDTLS, + NodeJsonStats, + OctreeDataNack, + StopNode, + AudioEnvironment, + EntityEditNack, + ICEServerHeartbeat, + ICEPing, + ICEPingReply, + EntityData, + EntityQuery, + EntityAdd, + EntityErase, + EntityEdit, + DomainServerConnectionToken, + DomainSettingsRequest, + DomainSettings, + AssetGet, + AssetGetReply, + AssetUpload, + AssetUploadReply, + AssetGetInfo, + AssetGetInfoReply, + NodeDisconnect + }; }; +using PacketType = PacketTypeEnum::Value; + const int NUM_BYTES_MD5_HASH = 16; typedef char PacketVersion; @@ -91,7 +100,6 @@ extern const QSet NON_VERIFIED_PACKETS; extern const QSet NON_SOURCED_PACKETS; extern const QSet RELIABLE_PACKETS; -QString nameForPacketType(PacketType packetType); PacketVersion versionForPacketType(PacketType packetType); uint qHash(const PacketType& key, uint seed); diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index cceb3ba706..fe92fe7745 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -1890,8 +1890,8 @@ bool Octree::readSVOFromStream(unsigned long streamLength, QDataStream& inputStr versionForPacketType(expectedDataPacketType()), gotVersion); } } else { - qCDebug(octree) << "SVO file type mismatch. Expected: " << nameForPacketType(expectedType) - << " Got: " << nameForPacketType(gotType); + qCDebug(octree) << "SVO file type mismatch. Expected: " << expectedType + << " Got: " << gotType; } } else { From 8bdb81d832723a944fd7dea220bc0f755950be2e Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 12 Nov 2015 15:03:19 -0800 Subject: [PATCH 34/61] send disconnect packet from node when leaving domain --- libraries/networking/src/DomainHandler.cpp | 22 +++++++++++++++++-- libraries/networking/src/DomainHandler.h | 3 ++- .../networking/src/udt/PacketHeaders.cpp | 10 +++++---- libraries/networking/src/udt/PacketHeaders.h | 3 ++- 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/libraries/networking/src/DomainHandler.cpp b/libraries/networking/src/DomainHandler.cpp index df024b361d..1a80f81bbe 100644 --- a/libraries/networking/src/DomainHandler.cpp +++ b/libraries/networking/src/DomainHandler.cpp @@ -46,7 +46,13 @@ DomainHandler::DomainHandler(QObject* parent) : connect(this, &DomainHandler::completedSocketDiscovery, &_icePeer, &NetworkPeer::stopPingTimer); } -void DomainHandler::clearConnectionInfo() { +void DomainHandler::disconnect() { + // if we're currently connected to a domain, send a disconnect packet on our way out + if (_isConnected) { + sendDisconnectPacket(); + } + + // clear member variables that hold the connection state to a domain _uuid = QUuid(); _connectionToken = QUuid(); @@ -60,6 +66,18 @@ void DomainHandler::clearConnectionInfo() { setIsConnected(false); } +void DomainHandler::sendDisconnectPacket() { + // The DomainDisconnect packet is not verified - we're relying on the eventual addition of DTLS to the + // domain-server connection to stop greifing here + + // construct the disconnect packet once (an empty packet but sourced with our current session UUID) + static auto disconnectPacket = NLPacket::create(PacketType::DomainDisconnect, 0); + + // send the disconnect packet to the current domain server + auto nodeList = DependencyManager::get(); + nodeList->sendUnreliablePacket(*disconnectPacket, _sockAddr); +} + void DomainHandler::clearSettings() { _settingsObject = QJsonObject(); _failedSettingsRequests = 0; @@ -67,7 +85,7 @@ void DomainHandler::clearSettings() { void DomainHandler::softReset() { qCDebug(networking) << "Resetting current domain connection information."; - clearConnectionInfo(); + disconnect(); clearSettings(); } diff --git a/libraries/networking/src/DomainHandler.h b/libraries/networking/src/DomainHandler.h index 9dd4254c30..da22c4527d 100644 --- a/libraries/networking/src/DomainHandler.h +++ b/libraries/networking/src/DomainHandler.h @@ -35,7 +35,6 @@ class DomainHandler : public QObject { public: DomainHandler(QObject* parent = 0); - void clearConnectionInfo(); void clearSettings(); const QUuid& getUUID() const { return _uuid; } @@ -113,6 +112,8 @@ signals: void settingsReceiveFail(); private: + void disconnect(); + void sendDisconnectPacket(); void hardReset(); QUuid _uuid; diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index b389d4d3df..95df09fb5c 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -19,7 +19,8 @@ const QSet NON_VERIFIED_PACKETS = QSet() << PacketType::NodeJsonStats << PacketType::EntityQuery << PacketType::OctreeDataNack << PacketType::EntityEditNack - << PacketType::DomainListRequest << PacketType::StopNode; + << PacketType::DomainListRequest << PacketType::StopNode + << PacketType::DomainDisconnect; const QSet NON_SOURCED_PACKETS = QSet() << PacketType::StunResponse << PacketType::CreateAssignment << PacketType::RequestAssignment @@ -30,7 +31,8 @@ const QSet NON_SOURCED_PACKETS = QSet() << PacketType::DomainSettingsRequest << PacketType::DomainSettings << PacketType::ICEServerPeerInformation << PacketType::ICEServerQuery << PacketType::ICEServerHeartbeat << PacketType::ICEPing << PacketType::ICEPingReply - << PacketType::AssignmentClientStatus << PacketType::StopNode; + << PacketType::AssignmentClientStatus << PacketType::StopNode + << PacketType::DomainServerRemovedNode; const QSet RELIABLE_PACKETS = QSet(); @@ -48,8 +50,8 @@ PacketVersion versionForPacketType(PacketType packetType) { } uint qHash(const PacketType& key, uint seed) { - // seems odd that Qt couldn't figure out this cast itself, but this fixes a compile error after switch to - // strongly typed enum for PacketType + // seems odd that Qt couldn't figure out this cast itself, but this fixes a compile error after switch + // to strongly typed enum for PacketType return qHash((quint8) key, seed); } diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 147c001ba9..4b5a6b5f52 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -86,7 +86,8 @@ public: AssetUploadReply, AssetGetInfo, AssetGetInfoReply, - NodeDisconnect + DomainDisconnect, + DomainServerRemovedNode }; }; From d7be1699a7f0d5e13e735029f2b9996daf69194f Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 12 Nov 2015 15:27:10 -0800 Subject: [PATCH 35/61] adjust how the decision to send action changes over the wire is made --- interface/src/avatar/AvatarActionHold.cpp | 3 ++- libraries/entities/src/EntityItem.cpp | 8 +++++--- libraries/entities/src/EntityItem.h | 14 ++++++++++---- libraries/physics/src/EntityMotionState.cpp | 3 ++- libraries/physics/src/ObjectActionOffset.cpp | 3 ++- libraries/physics/src/ObjectActionSpring.cpp | 3 ++- 6 files changed, 23 insertions(+), 11 deletions(-) diff --git a/interface/src/avatar/AvatarActionHold.cpp b/interface/src/avatar/AvatarActionHold.cpp index 0d86e79a2d..839f2d4fbb 100644 --- a/interface/src/avatar/AvatarActionHold.cpp +++ b/interface/src/avatar/AvatarActionHold.cpp @@ -211,7 +211,8 @@ bool AvatarActionHold::updateArguments(QVariantMap arguments) { auto ownerEntity = _ownerEntity.lock(); if (ownerEntity) { - ownerEntity->setActionDataNeedsUpdate(true); + ownerEntity->setActionDataDirty(true); + ownerEntity->setActionDataNeedsTransmit(true); } }); activateBody(); diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index ef39cf8063..807186a304 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1740,6 +1740,8 @@ void EntityItem::deserializeActionsInternal() { } } + _actionDataDirty = true; + return; } @@ -1800,11 +1802,11 @@ void EntityItem::serializeActions(bool& success, QByteArray& result) const { } const QByteArray EntityItem::getActionDataInternal() const { - if (_actionDataNeedsUpdate) { + if (_actionDataDirty) { bool success; serializeActions(success, _allActionsDataCache); if (success) { - _actionDataNeedsUpdate = false; + _actionDataDirty = false; } } return _allActionsDataCache; @@ -1814,7 +1816,7 @@ const QByteArray EntityItem::getActionData() const { QByteArray result; assertUnlocked(); - if (_actionDataNeedsUpdate) { + if (_actionDataDirty) { withWriteLock([&] { getActionDataInternal(); result = _allActionsDataCache; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 6e4f3ac2ca..5b47198e97 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -408,8 +408,13 @@ public: QList getActionIDs() { return _objectActions.keys(); } QVariantMap getActionArguments(const QUuid& actionID) const; void deserializeActions(); - void setActionDataNeedsUpdate(bool value) const { _actionDataNeedsUpdate = value; } - bool actionDataNeedsUpdate() const { return _actionDataNeedsUpdate; } + + void setActionDataDirty(bool value) const { _actionDataDirty = value; } + bool actionDataDirty() const { return _actionDataDirty; } + + void setActionDataNeedsTransmit(bool value) const { _actionDataNeedsTransmit = value; } + bool actionDataNeedsTransmit() const { return _actionDataNeedsTransmit; } + bool shouldSuppressLocationEdits() const; void setSourceUUID(const QUuid& sourceUUID) { _sourceUUID = sourceUUID; } @@ -442,7 +447,7 @@ protected: mutable bool _recalcAABox = true; mutable bool _recalcMinAACube = true; mutable bool _recalcMaxAACube = true; - + float _glowLevel; float _localRenderAlpha; float _density = ENTITY_ITEM_DEFAULT_DENSITY; // kg/m^3 @@ -512,7 +517,8 @@ protected: // are used to keep track of and work around this situation. void checkWaitingToRemove(EntitySimulation* simulation = nullptr); mutable QSet _actionsToRemove; - mutable bool _actionDataNeedsUpdate = false; + mutable bool _actionDataDirty = false; + mutable bool _actionDataNeedsTransmit = false; // _previouslyDeletedActions is used to avoid an action being re-added due to server round-trip lag static quint64 _rememberDeletedActionTime; mutable QHash _previouslyDeletedActions; diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 841a41cb04..03e1c1c5b7 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -297,8 +297,9 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) { _serverPosition += dt * _serverVelocity; } - if (_entity->actionDataNeedsUpdate()) { + if (_entity->actionDataNeedsTransmit()) { setOutgoingPriority(SCRIPT_EDIT_SIMULATION_PRIORITY); + _entity->setActionDataNeedsTransmit(false); return true; } diff --git a/libraries/physics/src/ObjectActionOffset.cpp b/libraries/physics/src/ObjectActionOffset.cpp index be2f5b40a0..5c2999a0a1 100644 --- a/libraries/physics/src/ObjectActionOffset.cpp +++ b/libraries/physics/src/ObjectActionOffset.cpp @@ -129,7 +129,8 @@ bool ObjectActionOffset::updateArguments(QVariantMap arguments) { auto ownerEntity = _ownerEntity.lock(); if (ownerEntity) { - ownerEntity->setActionDataNeedsUpdate(true); + ownerEntity->setActionDataDirty(true); + ownerEntity->setActionDataNeedsTransmit(true); } }); activateBody(); diff --git a/libraries/physics/src/ObjectActionSpring.cpp b/libraries/physics/src/ObjectActionSpring.cpp index 7289c88a8f..d9d6a323a7 100644 --- a/libraries/physics/src/ObjectActionSpring.cpp +++ b/libraries/physics/src/ObjectActionSpring.cpp @@ -162,7 +162,8 @@ bool ObjectActionSpring::updateArguments(QVariantMap arguments) { auto ownerEntity = _ownerEntity.lock(); if (ownerEntity) { - ownerEntity->setActionDataNeedsUpdate(true); + ownerEntity->setActionDataDirty(true); + ownerEntity->setActionDataNeedsTransmit(true); } }); activateBody(); From 1c9396d66e49ac392fc02ea72137f37bd974f93b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 12 Nov 2015 15:43:03 -0800 Subject: [PATCH 36/61] handle disconnect request in domain-server --- domain-server/src/DomainServer.cpp | 10 ++++++++++ domain-server/src/DomainServer.h | 3 ++- libraries/networking/src/DomainHandler.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 2 +- 5 files changed, 15 insertions(+), 4 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index b5fd9f2b20..b0aacd23f7 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -272,6 +272,7 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) { packetReceiver.registerListener(PacketType::DomainListRequest, this, "processListRequestPacket"); packetReceiver.registerListener(PacketType::DomainServerPathQuery, this, "processPathQueryPacket"); packetReceiver.registerMessageListener(PacketType::NodeJsonStats, this, "processNodeJSONStatsPacket"); + packetReceiver.registerListener(PacketType::DomainDisconnectRequest, this, "processNodeDisconnectRequestPacket"); // NodeList won't be available to the settings manager when it is created, so call registerListener here packetReceiver.registerListener(PacketType::DomainSettingsRequest, &_settingsManager, "processSettingsRequestPacket"); @@ -1826,3 +1827,12 @@ void DomainServer::processPathQueryPacket(QSharedPointer packet) { } } } + +void DomainServer::processNodeDisconnectRequestPacket(QSharedPointer packet) { + // This packet has been matched to a source node and they're asking not to be in the domain anymore + auto limitedNodeList = DependencyManager::get(); + + qDebug() << "Received a disconnect request from node with UUID" << packet->getSourceID(); + + limitedNodeList->killNodeWithUUID(packet->getSourceID()); +} diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index df42bf3ad9..e5b3d3b3fd 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -60,7 +60,8 @@ public slots: void processListRequestPacket(QSharedPointer packet, SharedNodePointer sendingNode); void processNodeJSONStatsPacket(QSharedPointer packetList, SharedNodePointer sendingNode); void processPathQueryPacket(QSharedPointer packet); - + void processNodeDisconnectRequestPacket(QSharedPointer packet); + private slots: void aboutToQuit(); diff --git a/libraries/networking/src/DomainHandler.cpp b/libraries/networking/src/DomainHandler.cpp index 1a80f81bbe..f7d26f25c5 100644 --- a/libraries/networking/src/DomainHandler.cpp +++ b/libraries/networking/src/DomainHandler.cpp @@ -71,7 +71,7 @@ void DomainHandler::sendDisconnectPacket() { // domain-server connection to stop greifing here // construct the disconnect packet once (an empty packet but sourced with our current session UUID) - static auto disconnectPacket = NLPacket::create(PacketType::DomainDisconnect, 0); + static auto disconnectPacket = NLPacket::create(PacketType::DomainDisconnectRequest, 0); // send the disconnect packet to the current domain server auto nodeList = DependencyManager::get(); diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 95df09fb5c..f5c66617a8 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -20,7 +20,7 @@ const QSet NON_VERIFIED_PACKETS = QSet() << PacketType::NodeJsonStats << PacketType::EntityQuery << PacketType::OctreeDataNack << PacketType::EntityEditNack << PacketType::DomainListRequest << PacketType::StopNode - << PacketType::DomainDisconnect; + << PacketType::DomainDisconnectRequest; const QSet NON_SOURCED_PACKETS = QSet() << PacketType::StunResponse << PacketType::CreateAssignment << PacketType::RequestAssignment diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 4b5a6b5f52..da061d8fdf 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -86,7 +86,7 @@ public: AssetUploadReply, AssetGetInfo, AssetGetInfoReply, - DomainDisconnect, + DomainDisconnectRequest, DomainServerRemovedNode }; }; From 6f83f32eccbc2726e9153c3bd3ea8f2e2d19b2ab Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 12 Nov 2015 16:27:54 -0800 Subject: [PATCH 37/61] adjust how the decision to send action changes over the wire is made --- libraries/physics/src/EntityMotionState.cpp | 43 ++++++++------------- libraries/physics/src/EntityMotionState.h | 1 - 2 files changed, 17 insertions(+), 27 deletions(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 03e1c1c5b7..66f5d46c18 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -87,15 +87,11 @@ void EntityMotionState::updateServerPhysicsVariables(const QUuid& sessionID) { } _serverActionData = _entity->getActionData(); - if (!_serverShouldSuppressLocationEdits) { - _serverPosition = _entity->getPosition(); - _serverRotation = _entity->getRotation(); - _serverVelocity = _entity->getVelocity(); - _serverAngularVelocity = _entity->getAngularVelocity(); - _serverAcceleration = _entity->getAcceleration(); - } - - _serverShouldSuppressLocationEdits = _entity->shouldSuppressLocationEdits(); + _serverPosition = _entity->getPosition(); + _serverRotation = _entity->getRotation(); + _serverVelocity = _entity->getVelocity(); + _serverAngularVelocity = _entity->getAngularVelocity(); + _serverAcceleration = _entity->getAcceleration(); } // virtual @@ -262,7 +258,6 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) { _serverAngularVelocity = bulletToGLM(_body->getAngularVelocity()); _lastStep = simulationStep; _serverActionData = _entity->getActionData(); - _serverShouldSuppressLocationEdits = _entity->shouldSuppressLocationEdits(); _sentInactive = true; return false; } @@ -448,24 +443,20 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, const Q EntityItemProperties properties; + // remember properties for local server prediction + _serverPosition = _entity->getPosition(); + _serverRotation = _entity->getRotation(); + _serverVelocity = _entity->getVelocity(); + _serverAcceleration = _entity->getAcceleration(); + _serverAngularVelocity = _entity->getAngularVelocity(); + _serverActionData = _entity->getActionData(); // explicitly set the properties that changed so that they will be packed - if (!_serverShouldSuppressLocationEdits) { - // remember properties for local server prediction - _serverPosition = _entity->getPosition(); - _serverRotation = _entity->getRotation(); - _serverVelocity = _entity->getVelocity(); - _serverAcceleration = _entity->getAcceleration(); - _serverAngularVelocity = _entity->getAngularVelocity(); - - properties.setPosition(_serverPosition); - properties.setRotation(_serverRotation); - properties.setVelocity(_serverVelocity); - properties.setAcceleration(_serverAcceleration); - properties.setAngularVelocity(_serverAngularVelocity); - } - _serverShouldSuppressLocationEdits = _entity->shouldSuppressLocationEdits(); - _serverActionData = _entity->getActionData(); + properties.setPosition(_serverPosition); + properties.setRotation(_serverRotation); + properties.setVelocity(_serverVelocity); + properties.setAcceleration(_serverAcceleration); + properties.setAngularVelocity(_serverAngularVelocity); properties.setActionData(_serverActionData); // set the LastEdited of the properties but NOT the entity itself diff --git a/libraries/physics/src/EntityMotionState.h b/libraries/physics/src/EntityMotionState.h index f70eff44a4..188e7096b9 100644 --- a/libraries/physics/src/EntityMotionState.h +++ b/libraries/physics/src/EntityMotionState.h @@ -110,7 +110,6 @@ protected: glm::vec3 _serverGravity; glm::vec3 _serverAcceleration; QByteArray _serverActionData; - bool _serverShouldSuppressLocationEdits = false; uint32_t _lastMeasureStep; glm::vec3 _lastVelocity; From 756b382a75981593971073257de5d89233e0219c Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 12 Nov 2015 17:12:20 -0800 Subject: [PATCH 38/61] adjust how the decision to send action changes over the wire is made --- libraries/physics/src/EntityMotionState.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 66f5d46c18..877ea168aa 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -86,12 +86,12 @@ void EntityMotionState::updateServerPhysicsVariables(const QUuid& sessionID) { return; } - _serverActionData = _entity->getActionData(); _serverPosition = _entity->getPosition(); _serverRotation = _entity->getRotation(); _serverVelocity = _entity->getVelocity(); _serverAngularVelocity = _entity->getAngularVelocity(); _serverAcceleration = _entity->getAcceleration(); + _serverActionData = _entity->getActionData(); } // virtual @@ -298,10 +298,6 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) { return true; } - if (_entity->shouldSuppressLocationEdits()) { - return false; - } - // Else we measure the error between current and extrapolated transform (according to expected behavior // of remote EntitySimulation) and return true if the error is significant. @@ -441,8 +437,6 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, const Q _sentInactive = false; } - EntityItemProperties properties; - // remember properties for local server prediction _serverPosition = _entity->getPosition(); _serverRotation = _entity->getRotation(); @@ -451,6 +445,8 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, const Q _serverAngularVelocity = _entity->getAngularVelocity(); _serverActionData = _entity->getActionData(); + EntityItemProperties properties; + // explicitly set the properties that changed so that they will be packed properties.setPosition(_serverPosition); properties.setRotation(_serverRotation); From e52e9be44ce26dedd5a3b380f3294f3c11004ba9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 12 Nov 2015 17:23:39 -0800 Subject: [PATCH 39/61] re-broadcast disconnects from domain-server --- domain-server/src/DomainServer.cpp | 18 ++++++++++++++++-- libraries/networking/src/DomainHandler.h | 2 +- .../networking/src/ThreadedAssignment.cpp | 9 +++++++-- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index b0aacd23f7..790548c5b3 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -1832,7 +1832,21 @@ void DomainServer::processNodeDisconnectRequestPacket(QSharedPointer p // This packet has been matched to a source node and they're asking not to be in the domain anymore auto limitedNodeList = DependencyManager::get(); - qDebug() << "Received a disconnect request from node with UUID" << packet->getSourceID(); + const QUuid& nodeUUID = packet->getSourceID(); - limitedNodeList->killNodeWithUUID(packet->getSourceID()); + qDebug() << "Received a disconnect request from node with UUID" << nodeUUID; + + if (limitedNodeList->nodeWithUUID(nodeUUID)) { + limitedNodeList->killNodeWithUUID(nodeUUID); + + static auto removedNodePacket = NLPacket::create(PacketType::DomainServerRemovedNode, NUM_BYTES_RFC4122_UUID); + + removedNodePacket->reset(); + removedNodePacket->write(nodeUUID.toRfc4122()); + + // broadcast out the DomainServerRemovedNode message + limitedNodeList->eachNode([&limitedNodeList](const SharedNodePointer& otherNode){ + limitedNodeList->sendUnreliablePacket(*removedNodePacket, *otherNode); + }); + } } diff --git a/libraries/networking/src/DomainHandler.h b/libraries/networking/src/DomainHandler.h index da22c4527d..49bab6dc28 100644 --- a/libraries/networking/src/DomainHandler.h +++ b/libraries/networking/src/DomainHandler.h @@ -35,6 +35,7 @@ class DomainHandler : public QObject { public: DomainHandler(QObject* parent = 0); + void disconnect(); void clearSettings(); const QUuid& getUUID() const { return _uuid; } @@ -112,7 +113,6 @@ signals: void settingsReceiveFail(); private: - void disconnect(); void sendDisconnectPacket(); void hardReset(); diff --git a/libraries/networking/src/ThreadedAssignment.cpp b/libraries/networking/src/ThreadedAssignment.cpp index 0422c03297..6855c2eec3 100644 --- a/libraries/networking/src/ThreadedAssignment.cpp +++ b/libraries/networking/src/ThreadedAssignment.cpp @@ -33,14 +33,19 @@ void ThreadedAssignment::setFinished(bool isFinished) { if (_isFinished) { qDebug() << "ThreadedAssignment::setFinished(true) called - finishing up."; - - auto& packetReceiver = DependencyManager::get()->getPacketReceiver(); + + auto nodeList = DependencyManager::get(); + + auto& packetReceiver = nodeList->getPacketReceiver(); // we should de-register immediately for any of our packets packetReceiver.unregisterListener(this); // we should also tell the packet receiver to drop packets while we're cleaning up packetReceiver.setShouldDropPackets(true); + + // send a disconnect packet to the domain + nodeList->getDomainHandler().disconnect(); if (_domainServerTimer) { // stop the domain-server check in timer by calling deleteLater so it gets cleaned up on NL thread From ed8a604e136dd257f090d34428cd7b92d04da7a5 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 12 Nov 2015 17:36:45 -0800 Subject: [PATCH 40/61] adjust how the decision to send action changes over the wire is made --- libraries/physics/src/EntityMotionState.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 877ea168aa..24957bbf30 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -244,7 +244,7 @@ bool EntityMotionState::isCandidateForOwnership(const QUuid& sessionID) const { return false; } assert(entityTreeIsLocked()); - return _outgoingPriority != NO_PRORITY || sessionID == _entity->getSimulatorID(); + return _outgoingPriority != NO_PRORITY || sessionID == _entity->getSimulatorID() || _entity->actionDataNeedsTransmit(); } bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) { @@ -298,6 +298,10 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) { return true; } + if (_entity->shouldSuppressLocationEdits()) { + return false; + } + // Else we measure the error between current and extrapolated transform (according to expected behavior // of remote EntitySimulation) and return true if the error is significant. From 6b2987eef8c3abb3c44952c8a6d739e0c866cf5c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 12 Nov 2015 17:47:51 -0800 Subject: [PATCH 41/61] handle domain server node removal in NodeList --- interface/src/Application.cpp | 10 +++++++++- libraries/networking/src/NodeList.cpp | 8 ++++++++ libraries/networking/src/NodeList.h | 1 + 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7a564bbbf0..2679d4b5ec 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -804,8 +804,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : void Application::aboutToQuit() { emit beforeAboutToQuit(); + getActiveDisplayPlugin()->deactivate(); + _aboutToQuit = true; + cleanupBeforeQuit(); } @@ -831,8 +834,13 @@ void Application::cleanupBeforeQuit() { _entities.clear(); // this will allow entity scripts to properly shutdown + auto nodeList = DependencyManager::get(); + + // send the domain a disconnect packet + nodeList->getDomainHandler().disconnect(); + // tell the packet receiver we're shutting down, so it can drop packets - DependencyManager::get()->getPacketReceiver().setShouldDropPackets(true); + nodeList->getPacketReceiver().setShouldDropPackets(true); _entities.shutdown(); // tell the entities system we're shutting down, so it will stop running scripts ScriptEngine::stopAllScripts(this); // stop all currently running global scripts diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index b262904c63..19ed8073c1 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -103,6 +103,7 @@ NodeList::NodeList(char newOwnerType, unsigned short socketListenPort, unsigned packetReceiver.registerListener(PacketType::DomainServerRequireDTLS, &_domainHandler, "processDTLSRequirementPacket"); packetReceiver.registerListener(PacketType::ICEPingReply, &_domainHandler, "processICEPingReplyPacket"); packetReceiver.registerListener(PacketType::DomainServerPathResponse, this, "processDomainServerPathResponse"); + packetReceiver.registerListener(PacketType::DomainServerRemovedNode, this, "processDomainServerRemovedNode"); } qint64 NodeList::sendStats(const QJsonObject& statsObject, const HifiSockAddr& destination) { @@ -513,6 +514,13 @@ void NodeList::processDomainServerAddedNode(QSharedPointer packet) { parseNodeFromPacketStream(packetStream); } +void NodeList::processDomainServerRemovedNode(QSharedPointer packet) { + // read the UUID from the packet, remove it if it exists + QUuid nodeUUID = QUuid::fromRfc4122(packet->readWithoutCopy(NUM_BYTES_RFC4122_UUID)); + qDebug() << "Received packet from domain-server to remove node with UUID" << uuidStringWithoutCurlyBraces(nodeUUID); + killNodeWithUUID(nodeUUID); +} + void NodeList::parseNodeFromPacketStream(QDataStream& packetStream) { // setup variables to read into from QDataStream qint8 nodeType; diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index 3aae3e3dfc..880f9b05f9 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -74,6 +74,7 @@ public slots: void processDomainServerList(QSharedPointer packet); void processDomainServerAddedNode(QSharedPointer packet); + void processDomainServerRemovedNode(QSharedPointer packet); void processDomainServerPathResponse(QSharedPointer packet); void processDomainServerConnectionTokenPacket(QSharedPointer packet); From 1fd37b51a2bced38a435128d327e0aa4269388b7 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 12 Nov 2015 17:54:35 -0800 Subject: [PATCH 42/61] trying to get somewhere.... --- examples/utilities/record/recorder.js | 2 + interface/src/avatar/MyAvatar.cpp | 2 +- libraries/avatars/src/AvatarData.cpp | 67 +++++++++++++++++++-------- libraries/avatars/src/AvatarData.h | 3 ++ 4 files changed, 54 insertions(+), 20 deletions(-) diff --git a/examples/utilities/record/recorder.js b/examples/utilities/record/recorder.js index 6d49030a28..13ea1e0c72 100644 --- a/examples/utilities/record/recorder.js +++ b/examples/utilities/record/recorder.js @@ -176,6 +176,8 @@ function formatTime(time) { var SEC_PER_MIN = 60; var MSEC_PER_SEC = 1000; + time = time * (MSEC_PER_SEC * SEC_PER_MIN * MIN_PER_HOUR); + var hours = Math.floor(time / (MSEC_PER_SEC * SEC_PER_MIN * MIN_PER_HOUR)); time -= hours * (MSEC_PER_SEC * SEC_PER_MIN * MIN_PER_HOUR); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 5e14c66ff1..4d62946a5f 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -608,7 +608,7 @@ float MyAvatar::recorderElapsed() { if (!_recorder) { return 0; } - return (float)_recorder->position() / MSECS_PER_SECOND; + return (float)_recorder->position(); } QMetaObject::Connection _audioClientRecorderConnection; diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index adf471c50e..e2d2c05ef6 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -804,12 +804,12 @@ float AvatarData::playerElapsed() { return 0; } if (QThread::currentThread() != thread()) { - qint64 result; + float result; QMetaObject::invokeMethod(this, "playerElapsed", Qt::BlockingQueuedConnection, - Q_RETURN_ARG(qint64, result)); + Q_RETURN_ARG(float, result)); return result; } - return (float)_player->position() / MSECS_PER_SECOND; + return (float)_player->position(); } float AvatarData::playerLength() { @@ -817,12 +817,12 @@ float AvatarData::playerLength() { return 0; } if (QThread::currentThread() != thread()) { - qint64 result; + float result; QMetaObject::invokeMethod(this, "playerLength", Qt::BlockingQueuedConnection, - Q_RETURN_ARG(qint64, result)); + Q_RETURN_ARG(float, result)); return result; } - return _player->length() / MSECS_PER_SECOND; + return _player->length(); } void AvatarData::loadRecording(const QString& filename) { @@ -870,7 +870,7 @@ void AvatarData::setPlayerTime(float time) { return; } - _player->seek(time * MSECS_PER_SECOND); + _player->seek(time); } void AvatarData::setPlayFromCurrentLocation(bool playFromCurrentLocation) { @@ -1532,7 +1532,7 @@ Transform AvatarData::getTransform() const { static const QString JSON_AVATAR_BASIS = QStringLiteral("basisTransform"); static const QString JSON_AVATAR_RELATIVE = QStringLiteral("relativeTransform"); -static const QString JSON_AVATAR_JOINT_ROTATIONS = QStringLiteral("jointRotations"); +static const QString JSON_AVATAR_JOINT_ARRAY = QStringLiteral("jointArray"); static const QString JSON_AVATAR_HEAD = QStringLiteral("head"); static const QString JSON_AVATAR_HEAD_ROTATION = QStringLiteral("rotation"); static const QString JSON_AVATAR_HEAD_BLENDSHAPE_COEFFICIENTS = QStringLiteral("blendShapes"); @@ -1544,6 +1544,24 @@ static const QString JSON_AVATAR_BODY_MODEL = QStringLiteral("bodyModel"); static const QString JSON_AVATAR_DISPLAY_NAME = QStringLiteral("displayName"); static const QString JSON_AVATAR_ATTACHEMENTS = QStringLiteral("attachments"); +QJsonValue toJsonValue(const JointData& joint) { + QJsonArray result; + result.push_back(toJsonValue(joint.rotation)); + result.push_back(toJsonValue(joint.translation)); + return result; +} + +JointData jointDataFromJsonValue(const QJsonValue& json) { + JointData result; + if (json.isArray()) { + QJsonArray array = json.toArray(); + result.rotation = quatFromJsonValue(array[0]); + result.rotationSet = true; + result.translation = vec3FromJsonValue(array[1]); + result.translationSet = false; + } + return result; +} // Every frame will store both a basis for the recording and a relative transform // This allows the application to decide whether playback should be relative to an avatar's @@ -1575,13 +1593,16 @@ QByteArray avatarStateToFrame(const AvatarData* _avatar) { root[JSON_AVATAR_RELATIVE] = Transform::toJson(relativeTransform); root[JSON_AVATAR_BASIS] = Transform::toJson(*recordingBasis); } + } else { + root[JSON_AVATAR_RELATIVE] = Transform::toJson(_avatar->getTransform()); } - QJsonArray jointRotations; - for (const auto& jointRotation : _avatar->getJointRotations()) { - jointRotations.push_back(toJsonValue(jointRotation)); + // Skeleton pose + QJsonArray jointArray; + for (const auto& joint : _avatar->getRawJointData()) { + jointArray.push_back(toJsonValue(joint)); } - root[JSON_AVATAR_JOINT_ROTATIONS] = jointRotations; + root[JSON_AVATAR_JOINT_ARRAY] = jointArray; const HeadData* head = _avatar->getHeadData(); if (head) { @@ -1646,21 +1667,29 @@ void avatarStateFromFrame(const QByteArray& frameData, AvatarData* _avatar) { _avatar->setTargetScale(worldTransform.getScale().x); } -#if 0 + if (root.contains(JSON_AVATAR_ATTACHEMENTS)) { // FIXME de-serialize attachment data } // Joint rotations are relative to the avatar, so they require no basis correction - if (root.contains(JSON_AVATAR_JOINT_ROTATIONS)) { - QVector jointRotations; - QJsonArray jointRotationsJson = root[JSON_AVATAR_JOINT_ROTATIONS].toArray(); - jointRotations.reserve(jointRotationsJson.size()); - for (const auto& jointRotationJson : jointRotationsJson) { - jointRotations.push_back(quatFromJsonValue(jointRotationJson)); + if (root.contains(JSON_AVATAR_JOINT_ARRAY)) { + QVector jointArray; + QJsonArray jointArrayJson = root[JSON_AVATAR_JOINT_ARRAY].toArray(); + jointArray.reserve(jointArrayJson.size()); + for (const auto& jointJson : jointArrayJson) { + jointArray.push_back(jointDataFromJsonValue(jointJson)); } + + QVector jointRotations; + jointRotations.reserve(jointArray.size()); + for (const auto& joint : jointArray) { + jointRotations.push_back(joint.rotation); + } + _avatar->setJointRotations(jointRotations); } +#if 0 // Most head data is relative to the avatar, and needs no basis correction, // but the lookat vector does need correction HeadData* head = _avatar->_headData; diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 7716a16a1c..26bc9d83ff 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -457,6 +457,9 @@ public: bool translationSet = false; }; +QJsonValue toJsonValue(const JointData& joint); +JointData jointDataFromJsonValue(const QJsonValue& q); + class AttachmentData { public: QUrl modelURL; From d932ba74fd75ef2244a165ad76c5e182fd9d4d67 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 12 Nov 2015 17:58:12 -0800 Subject: [PATCH 43/61] remove the avatar kill packet from Interface --- interface/src/Application.cpp | 5 +---- interface/src/avatar/MyAvatar.cpp | 5 ----- interface/src/avatar/MyAvatar.h | 2 -- 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2679d4b5ec..f8d958c82e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -836,7 +836,7 @@ void Application::cleanupBeforeQuit() { auto nodeList = DependencyManager::get(); - // send the domain a disconnect packet + // send the domain a disconnect packet, force a clear of the IP so we can't nodeList->getDomainHandler().disconnect(); // tell the packet receiver we're shutting down, so it can drop packets @@ -860,9 +860,6 @@ void Application::cleanupBeforeQuit() { saveSettings(); _window->saveGeometry(); - // let the avatar mixer know we're out - MyAvatar::sendKillAvatar(); - // stop the AudioClient QMetaObject::invokeMethod(DependencyManager::get().data(), "stop", Qt::BlockingQueuedConnection); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 852e1d1389..a59b26b51a 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1024,11 +1024,6 @@ int MyAvatar::parseDataFromBuffer(const QByteArray& buffer) { return buffer.size(); } -void MyAvatar::sendKillAvatar() { - auto killPacket = NLPacket::create(PacketType::KillAvatar, 0); - DependencyManager::get()->broadcastToNodes(std::move(killPacket), NodeSet() << NodeType::AvatarMixer); -} - void MyAvatar::updateLookAtTargetAvatar() { // // Look at the avatar whose eyes are closest to the ray in direction of my avatar's head diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 52f1ffce3f..bb5fd0cf0a 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -162,8 +162,6 @@ public: eyeContactTarget getEyeContactTarget(); - static void sendKillAvatar(); - Q_INVOKABLE glm::vec3 getTrackedHeadPosition() const { return _trackedHeadPosition; } Q_INVOKABLE glm::vec3 getHeadPosition() const { return getHead()->getPosition(); } Q_INVOKABLE float getHeadFinalYaw() const { return getHead()->getFinalYaw(); } From ea38c4cc49e90b98f9ccf92d9634a69658b5ebb6 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 12 Nov 2015 18:04:15 -0800 Subject: [PATCH 44/61] don't allow domain check-ins while shutting down --- interface/src/Application.cpp | 3 ++- libraries/networking/src/NodeList.cpp | 4 ++++ libraries/networking/src/NodeList.h | 3 +++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f8d958c82e..37ea5405da 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -836,8 +836,9 @@ void Application::cleanupBeforeQuit() { auto nodeList = DependencyManager::get(); - // send the domain a disconnect packet, force a clear of the IP so we can't + // send the domain a disconnect packet, force stoppage of domain-server check-ins nodeList->getDomainHandler().disconnect(); + nodeList->setIsShuttingDown(true); // tell the packet receiver we're shutting down, so it can drop packets nodeList->getPacketReceiver().setShouldDropPackets(true); diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 19ed8073c1..e03ac47854 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -219,6 +219,10 @@ void NodeList::addSetOfNodeTypesToNodeInterestSet(const NodeSet& setOfNodeTypes) } void NodeList::sendDomainServerCheckIn() { + if (_isShuttingDown) { + qCDebug(networking) << "Refusing to send a domain-server check in while shutting down."; + } + if (_publicSockAddr.isNull()) { // we don't know our public socket and we need to send it to the domain server qCDebug(networking) << "Waiting for inital public socket from STUN. Will not send domain-server check in."; diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index 880f9b05f9..5b9a4e5ae5 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -66,6 +66,8 @@ public: void setAssignmentServerSocket(const HifiSockAddr& serverSocket) { _assignmentServerSocket = serverSocket; } void sendAssignment(Assignment& assignment); + + void setIsShuttingDown(bool isShuttingDown) { _isShuttingDown = isShuttingDown; } public slots: void reset(); @@ -115,6 +117,7 @@ private: DomainHandler _domainHandler; int _numNoReplyDomainCheckIns; HifiSockAddr _assignmentServerSocket; + bool _isShuttingDown { false }; }; #endif // hifi_NodeList_h From dbaea5770aba054360001819fbbd454f4242c93d Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 12 Nov 2015 18:28:26 -0800 Subject: [PATCH 45/61] include action data in properties suppressed by non-simulation ownership --- libraries/entities/src/EntityTree.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 0e2b713b65..7cbdc8b666 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -198,6 +198,7 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI properties.setVelocityChanged(false); properties.setAngularVelocityChanged(false); properties.setAccelerationChanged(false); + properties.setActionDataChanged(false); if (wantTerseEditLogging()) { qCDebug(entities) << senderNode->getUUID() << "physical edits suppressed"; From 89d120ab3d42ca26f7536961d861b29e009847c2 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 12 Nov 2015 22:24:11 -0800 Subject: [PATCH 46/61] Few fixes to make the recorder.js run --- examples/utilities/record/recorder.js | 2 +- libraries/avatars/src/AvatarData.cpp | 6 +++--- libraries/recording/src/recording/Deck.cpp | 2 ++ libraries/recording/src/recording/Frame.h | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/examples/utilities/record/recorder.js b/examples/utilities/record/recorder.js index 13ea1e0c72..b44cb23aa8 100644 --- a/examples/utilities/record/recorder.js +++ b/examples/utilities/record/recorder.js @@ -176,7 +176,7 @@ function formatTime(time) { var SEC_PER_MIN = 60; var MSEC_PER_SEC = 1000; - time = time * (MSEC_PER_SEC * SEC_PER_MIN * MIN_PER_HOUR); + time = time * (MSEC_PER_SEC); var hours = Math.floor(time / (MSEC_PER_SEC * SEC_PER_MIN * MIN_PER_HOUR)); time -= hours * (MSEC_PER_SEC * SEC_PER_MIN * MIN_PER_HOUR); diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index e2d2c05ef6..e44219977b 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -809,7 +809,7 @@ float AvatarData::playerElapsed() { Q_RETURN_ARG(float, result)); return result; } - return (float)_player->position(); + return (float)_player->position() / (float) MSECS_PER_SECOND; } float AvatarData::playerLength() { @@ -822,7 +822,7 @@ float AvatarData::playerLength() { Q_RETURN_ARG(float, result)); return result; } - return _player->length(); + return (float)_player->length() / (float) MSECS_PER_SECOND; } void AvatarData::loadRecording(const QString& filename) { @@ -870,7 +870,7 @@ void AvatarData::setPlayerTime(float time) { return; } - _player->seek(time); + _player->seek(time * MSECS_PER_SECOND); } void AvatarData::setPlayFromCurrentLocation(bool playFromCurrentLocation) { diff --git a/libraries/recording/src/recording/Deck.cpp b/libraries/recording/src/recording/Deck.cpp index 4349a39732..10209c26d7 100644 --- a/libraries/recording/src/recording/Deck.cpp +++ b/libraries/recording/src/recording/Deck.cpp @@ -25,6 +25,8 @@ void Deck::queueClip(ClipPointer clip, Time timeOffset) { // FIXME if the time offset is not zero, wrap the clip in a OffsetClip wrapper _clips.push_back(clip); + + _length = std::max(_length, clip->duration()); } void Deck::play() { diff --git a/libraries/recording/src/recording/Frame.h b/libraries/recording/src/recording/Frame.h index 85f5246a4e..f0f53ce144 100644 --- a/libraries/recording/src/recording/Frame.h +++ b/libraries/recording/src/recording/Frame.h @@ -27,7 +27,7 @@ public: static const FrameType TYPE_INVALID = 0xFFFF; static const FrameType TYPE_HEADER = 0x0; FrameType type { TYPE_INVALID }; - Time timeOffset { 0 }; + Time timeOffset { 0 }; // milliseconds QByteArray data; Frame() {} From 7979fb38cfa526bcd300f7b37726f5ffdc76a6fd Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 13 Nov 2015 09:25:17 -0800 Subject: [PATCH 47/61] don't always send actiondata along with other physics related properties --- libraries/entities/src/EntityTree.cpp | 1 - libraries/physics/src/EntityMotionState.cpp | 6 ++++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 7cbdc8b666..0e2b713b65 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -198,7 +198,6 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI properties.setVelocityChanged(false); properties.setAngularVelocityChanged(false); properties.setAccelerationChanged(false); - properties.setActionDataChanged(false); if (wantTerseEditLogging()) { qCDebug(entities) << senderNode->getUUID() << "physical edits suppressed"; diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 24957bbf30..759b87f6c6 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -294,7 +294,6 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) { if (_entity->actionDataNeedsTransmit()) { setOutgoingPriority(SCRIPT_EDIT_SIMULATION_PRIORITY); - _entity->setActionDataNeedsTransmit(false); return true; } @@ -457,7 +456,10 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, const Q properties.setVelocity(_serverVelocity); properties.setAcceleration(_serverAcceleration); properties.setAngularVelocity(_serverAngularVelocity); - properties.setActionData(_serverActionData); + if (_entity->actionDataNeedsTransmit()) { + _entity->setActionDataNeedsTransmit(false); + properties.setActionData(_serverActionData); + } // set the LastEdited of the properties but NOT the entity itself quint64 now = usecTimestampNow(); From 5acbb7436262cd5abefcb07be85c1d3d158fbda7 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 13 Nov 2015 09:45:06 -0800 Subject: [PATCH 48/61] send to network when an action is deleted, also --- libraries/entities/src/EntityItem.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 807186a304..d4eab00075 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1749,6 +1749,7 @@ void EntityItem::checkWaitingToRemove(EntitySimulation* simulation) { assertLocked(); foreach(QUuid actionID, _actionsToRemove) { removeActionInternal(actionID, simulation); + setActionDataNeedsTransmit(true); } _actionsToRemove.clear(); } From 3f7f5a2bbd7c3015b0fe38e4a296d69e0112e56c Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 13 Nov 2015 09:49:31 -0800 Subject: [PATCH 49/61] send to network when an action is deleted, also --- libraries/entities/src/EntityItem.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index d4eab00075..d434f0bb7f 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1749,6 +1749,7 @@ void EntityItem::checkWaitingToRemove(EntitySimulation* simulation) { assertLocked(); foreach(QUuid actionID, _actionsToRemove) { removeActionInternal(actionID, simulation); + setActionDataDirty(true); setActionDataNeedsTransmit(true); } _actionsToRemove.clear(); From 6ec5b12081bd52b1ba602e824d5d1918208fc27e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 13 Nov 2015 09:52:35 -0800 Subject: [PATCH 50/61] send to network when an action is deleted, also --- libraries/entities/src/EntityItem.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index d434f0bb7f..4456f2e751 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1629,6 +1629,7 @@ bool EntityItem::removeActionInternal(const QUuid& actionID, EntitySimulation* s bool success = true; serializeActions(success, _allActionsDataCache); _dirtyFlags |= Simulation::DIRTY_PHYSICS_ACTIVATION; + setActionDataNeedsTransmit(true); return success; } return false; @@ -1749,8 +1750,6 @@ void EntityItem::checkWaitingToRemove(EntitySimulation* simulation) { assertLocked(); foreach(QUuid actionID, _actionsToRemove) { removeActionInternal(actionID, simulation); - setActionDataDirty(true); - setActionDataNeedsTransmit(true); } _actionsToRemove.clear(); } From 1d0a2ddd3d80cdbb17b1427c291461837a37a082 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 13 Nov 2015 11:15:57 -0800 Subject: [PATCH 51/61] grab debugging script --- examples/grabInspector.js | 137 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 examples/grabInspector.js diff --git a/examples/grabInspector.js b/examples/grabInspector.js new file mode 100644 index 0000000000..8a027f819a --- /dev/null +++ b/examples/grabInspector.js @@ -0,0 +1,137 @@ +// +// grabInspector.js +// examples +// +// Created by Seth Alves on 2015-9-30. +// 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 +// + +Script.include("libraries/utils.js"); + +var INSPECT_RADIUS = 10; +var overlays = {}; + +var toType = function(obj) { + return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase() +} + +function grabDataToString(grabData) { + var result = ""; + + for (var argumentName in grabData) { + if (grabData.hasOwnProperty(argumentName)) { + if (argumentName == "type") { + continue; + } + var arg = grabData[argumentName]; + var argType = toType(arg); + var argString = arg; + if (argType == "object") { + if (Object.keys(arg).length == 3) { + argString = vec3toStr(arg, 1); + } + } else if (argType == "number") { + argString = arg.toFixed(2); + } + result += argumentName + ": " + // + toType(arg) + " -- " + + argString + "\n"; + } + } + + return result; +} + + + +function updateOverlay(entityID, grabText) { + var properties = Entities.getEntityProperties(entityID, ["position", "dimensions"]); + var position = Vec3.sum(properties.position, {x:0, y:properties.dimensions.y, z:0}); + if (entityID in overlays) { + var overlay = overlays[entityID]; + Overlays.editOverlay(overlay, { + text: grabText, + position: position + }); + } else { + var lines = grabText.split(/\r\n|\r|\n/); + + var maxLineLength = lines[0].length; + for (var i = 1; i < lines.length; i++) { + if (lines[i].length > maxLineLength) { + maxLineLength = lines[i].length; + } + } + + var textWidth = maxLineLength * 0.034; // XXX how to know this? + var textHeight = .5; + var numberOfLines = lines.length; + var textMargin = 0.05; + var lineHeight = (textHeight - (2 * textMargin)) / numberOfLines; + + overlays[entityID] = Overlays.addOverlay("text3d", { + position: position, + dimensions: { x: textWidth, y: textHeight }, + backgroundColor: { red: 0, green: 0, blue: 0}, + color: { red: 255, green: 255, blue: 255}, + topMargin: textMargin, + leftMargin: textMargin, + bottomMargin: textMargin, + rightMargin: textMargin, + text: grabText, + lineHeight: lineHeight, + alpha: 0.9, + backgroundAlpha: 0.9, + ignoreRayIntersection: true, + visible: true, + isFacingAvatar: true + }); + } +} + + +function cleanup() { + for (var entityID in overlays) { + Overlays.deleteOverlay(overlays[entityID]); + } +} + + +Script.setInterval(function() { + var nearbyEntities = Entities.findEntities(MyAvatar.position, INSPECT_RADIUS); + for (var entityIndex = 0; entityIndex < nearbyEntities.length; entityIndex++) { + var entityID = nearbyEntities[entityIndex]; + var userData = getEntityUserData(entityID); + var grabData = userData["grabKey"] + + // {"grabbableKey":{"invertSolidWhileHeld":true}, + // "grabKey":{"activated":true,"avatarId":"{6ea8b092-10e0-4058-888b-6facc40d0fe9}","refCount":1,"gravity":{"x":0,"y":0,"z":0},"ignoreForCollisions":0,"collisionsWillMove":1} + // } + + if (typeof grabData != 'undefined') { + var grabText = grabDataToString(grabData); + updateOverlay(entityID, grabText); + } else { + if (entityID in overlays) { + Overlays.deleteOverlay(overlays[entityID]); + delete overlays[entityID]; + } + } + } + + // if an entity is too far away, remove its overlay + for (var entityID in overlays) { + var position = Entities.getEntityProperties(entityID, ["position"]).position; + if (Vec3.distance(position, MyAvatar.position) > INSPECT_RADIUS) { + Overlays.deleteOverlay(overlays[entityID]); + delete overlays[entityID]; + } + } + +}, 100); + + +Script.scriptEnding.connect(cleanup); From 919ea5f1a05f42645db8678f79af83cd9e264058 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 13 Nov 2015 12:37:07 -0800 Subject: [PATCH 52/61] send action updates even if we aren't the simulation owner --- libraries/physics/src/EntityMotionState.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 759b87f6c6..181ae7060e 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -370,6 +370,10 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationStep, const QUuid& s assert(_body); assert(entityTreeIsLocked()); + if (_entity->actionDataNeedsTransmit()) { + return true; + } + if (_entity->getSimulatorID() != sessionID) { // we don't own the simulation, but maybe we should... if (_outgoingPriority != NO_PRORITY) { From 37469206552b12e270cdabf5a8323f227e33edae Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 13 Nov 2015 13:56:30 -0800 Subject: [PATCH 53/61] allow action updates from others when we are the simulation owner --- examples/grab.js | 4 +++- libraries/entities/src/EntityItem.cpp | 12 +----------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/examples/grab.js b/examples/grab.js index ee6c3c4de5..1637e1bcf2 100644 --- a/examples/grab.js +++ b/examples/grab.js @@ -506,6 +506,7 @@ Grabber.prototype.activateEntity = function(entityID, grabbedProperties) { if (data["refCount"] == 1) { data["gravity"] = grabbedProperties.gravity; data["ignoreForCollisions"] = grabbedProperties.ignoreForCollisions; + data["collisionsWillMove"] = grabbedProperties.collisionsWillMove; var whileHeldProperties = {gravity: {x:0, y:0, z:0}}; if (invertSolidWhileHeld) { whileHeldProperties["ignoreForCollisions"] = ! grabbedProperties.ignoreForCollisions; @@ -522,7 +523,8 @@ Grabber.prototype.deactivateEntity = function(entityID) { if (data["refCount"] < 1) { Entities.editEntity(entityID, { gravity: data["gravity"], - ignoreForCollisions: data["ignoreForCollisions"] + ignoreForCollisions: data["ignoreForCollisions"], + collisionsWillMove: data["collisionsWillMove"] }); data = null; } diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 4456f2e751..f032dcd347 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -707,17 +707,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY(PROP_COLLISION_SOUND_URL, QString, setCollisionSoundURL); READ_ENTITY_PROPERTY(PROP_HREF, QString, setHref); READ_ENTITY_PROPERTY(PROP_DESCRIPTION, QString, setDescription); - - { // When we own the simulation we don't accept updates to the entity's actions - // but since we're using macros below we have to temporarily modify overwriteLocalData. - // NOTE: this prevents userB from adding an action to an object1 when UserA - // has simulation ownership of it. - // TODO: figure out how to allow multiple users to update actions simultaneously - bool oldOverwrite = overwriteLocalData; - overwriteLocalData = overwriteLocalData && !weOwnSimulation; - READ_ENTITY_PROPERTY(PROP_ACTION_DATA, QByteArray, setActionData); - overwriteLocalData = oldOverwrite; - } + READ_ENTITY_PROPERTY(PROP_ACTION_DATA, QByteArray, setActionData); bytesRead += readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, propertyFlags, overwriteLocalData, somethingChanged); From 3b6b56f316574fd8d41c02e05e6b92c6d133705e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 13 Nov 2015 14:26:43 -0800 Subject: [PATCH 54/61] formatting --- libraries/render/src/render/DrawStatus.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/render/src/render/DrawStatus.h b/libraries/render/src/render/DrawStatus.h index 83be3112e0..1239819911 100644 --- a/libraries/render/src/render/DrawStatus.h +++ b/libraries/render/src/render/DrawStatus.h @@ -21,8 +21,8 @@ namespace render { int _drawItemBoundDimLoc = -1; int _drawItemStatusPosLoc = -1; int _drawItemStatusDimLoc = -1; - int _drawItemStatusValue0Loc = -1; - int _drawItemStatusValue1Loc = -1; + int _drawItemStatusValue0Loc = -1; + int _drawItemStatusValue1Loc = -1; gpu::Stream::FormatPointer _drawItemFormat; gpu::PipelinePointer _drawItemBoundsPipeline; From eb0d91fc7eca8405b17006bb7ff760a88ac5a60b Mon Sep 17 00:00:00 2001 From: EdgarPironti Date: Thu, 12 Nov 2015 18:25:51 -0800 Subject: [PATCH 55/61] Fixes to Master recording for ACs --- examples/acScripts/ControlACs.js | 57 +++++++++++++++--------------- examples/acScripts/ControlledAC.js | 54 ++++++++++++---------------- 2 files changed, 51 insertions(+), 60 deletions(-) diff --git a/examples/acScripts/ControlACs.js b/examples/acScripts/ControlACs.js index 60b72446bb..c0d5043e26 100644 --- a/examples/acScripts/ControlACs.js +++ b/examples/acScripts/ControlACs.js @@ -33,15 +33,6 @@ var SHOW = 4; var HIDE = 5; var LOAD = 6; -var COLORS = []; -COLORS[PLAY] = { red: PLAY, green: 0, blue: 0 }; -COLORS[PLAY_LOOP] = { red: PLAY_LOOP, green: 0, blue: 0 }; -COLORS[STOP] = { red: STOP, green: 0, blue: 0 }; -COLORS[SHOW] = { red: SHOW, green: 0, blue: 0 }; -COLORS[HIDE] = { red: HIDE, green: 0, blue: 0 }; -COLORS[LOAD] = { red: LOAD, green: 0, blue: 0 }; - - var windowDimensions = Controller.getViewportDimensions(); var TOOL_ICON_URL = HIFI_PUBLIC_BUCKET + "images/tools/"; @@ -138,6 +129,7 @@ function setupToolBars() { } function sendCommand(id, action) { + if (action === SHOW) { toolBars[id].selectTool(onOffIcon[id], false); toolBars[id].setAlpha(ALPHA_ON, playIcon[id]); @@ -154,24 +146,29 @@ function sendCommand(id, action) { return; } - if (id === (toolBars.length - 1)) { - for (i = 0; i < NUM_AC; i++) { - sendCommand(i, action); - } - return; - } + if (id === (toolBars.length - 1)) + id = -1; - var position = { x: controlEntityPosition.x + id * controlEntitySize, - y: controlEntityPosition.y, z: controlEntityPosition.z }; - Entities.addEntity({ - name: "Actor Controller", - userData: clip_url, + var controlEntity = Entities.addEntity({ + name: 'New Actor Controller', type: "Box", - position: position, - dimensions: { x: controlEntitySize, y: controlEntitySize, z: controlEntitySize }, - color: COLORS[action], - lifetime: 5 - }); + color: { red: 0, green: 0, blue: 0 }, + position: controlEntityPosition, + dimensions: { x: controlEntitySize, y: controlEntitySize, z: controlEntitySize }, + visible: false, + lifetime: 10, + userData: JSON.stringify({ + idKey: { + uD_id: id + }, + actionKey: { + uD_action: action + }, + clipKey: { + uD_url: clip_url + } + }) + }); } function mousePressEvent(event) { @@ -191,8 +188,12 @@ function mousePressEvent(event) { sendCommand(i, PLAY_LOOP); } else if (stopIcon[i] === toolBars[i].clicked(clickedOverlay, false)) { sendCommand(i, STOP); - } else if (loadIcon[i] === toolBars[i].clicked(clickedOverlay, false)) { - sendCommand(i, LOAD); + } else if (loadIcon[i] === toolBars[i].clicked(clickedOverlay, false)) { + input_text = Window.prompt("Insert the url of the clip: ",""); + if(!(input_text === "" || input_text === null)) { + clip_url = input_text; + sendCommand(i, LOAD); + } } else { // Check individual controls for (i = 0; i < NUM_AC; i++) { @@ -210,7 +211,7 @@ function mousePressEvent(event) { sendCommand(i, STOP); } else if (loadIcon[i] === toolBars[i].clicked(clickedOverlay, false)) { input_text = Window.prompt("Insert the url of the clip: ",""); - if(!(input_text === "" || input_text === null)){ + if(!(input_text === "" || input_text === null)) { clip_url = input_text; sendCommand(i, LOAD); } diff --git a/examples/acScripts/ControlledAC.js b/examples/acScripts/ControlledAC.js index 4eecc11136..de31f66df7 100644 --- a/examples/acScripts/ControlledAC.js +++ b/examples/acScripts/ControlledAC.js @@ -38,18 +38,6 @@ var SHOW = 4; var HIDE = 5; var LOAD = 6; -var COLORS = []; -COLORS[PLAY] = { red: PLAY, green: 0, blue: 0 }; -COLORS[PLAY_LOOP] = { red: PLAY_LOOP, green: 0, blue: 0 }; -COLORS[STOP] = { red: STOP, green: 0, blue: 0 }; -COLORS[SHOW] = { red: SHOW, green: 0, blue: 0 }; -COLORS[HIDE] = { red: HIDE, green: 0, blue: 0 }; -COLORS[LOAD] = { red: LOAD, green: 0, blue: 0 }; - -controlEntityPosition.x += id * controlEntitySize; - -Avatar.loadRecording(clip_url); - Avatar.setPlayFromCurrentLocation(playFromCurrentLocation); Avatar.setPlayerUseDisplayName(useDisplayName); Avatar.setPlayerUseAttachments(useAttachments); @@ -67,27 +55,29 @@ function setupEntityViewer() { EntityViewer.queryOctree(); } -function getAction(controlEntity) { - clip_url = controlEntity.userData; +function getAction(controlEntity) { + if (controlEntity === null) { + return DO_NOTHING; + } + + var userData = JSON.parse(Entities.getEntityProperties(controlEntity, ["userData"]).userData); - if (controlEntity === null || - controlEntity.position.x !== controlEntityPosition.x || - controlEntity.position.y !== controlEntityPosition.y || - controlEntity.position.z !== controlEntityPosition.z || - controlEntity.dimensions.x !== controlEntitySize) { + var uD_id = userData.idKey.uD_id; + var uD_action = userData.actionKey.uD_action; + var uD_url = userData.clipKey.uD_url; + + print("Sono " + id + " e ho ricevuto un comando da " + uD_id); + + Entities.deleteEntity((Entities.getEntityProperties(controlEntity)).id); + + if(uD_id === id || uD_id === -1) { + if(uD_action === 6) + clip_url = uD_url; + + return uD_action; + } else { return DO_NOTHING; - } - - for (i in COLORS) { - if (controlEntity.color.red === COLORS[i].red && - controlEntity.color.green === COLORS[i].green && - controlEntity.color.blue === COLORS[i].blue) { - Entities.deleteEntity(controlEntity.id); - return parseInt(i); - } - } - - return DO_NOTHING; + } } count = 100; // This is necessary to wait for the audio mixer to connect @@ -100,7 +90,7 @@ function update(event) { var controlEntity = Entities.findClosestEntity(controlEntityPosition, controlEntitySize); - var action = getAction(Entities.getEntityProperties(controlEntity)); + var action = getAction(controlEntity); switch(action) { case PLAY: From a80871a7a85b2c70f3152db238fd06a74eea78c1 Mon Sep 17 00:00:00 2001 From: EdgarPironti Date: Fri, 13 Nov 2015 14:58:59 -0800 Subject: [PATCH 56/61] Fixes --- examples/acScripts/ControlACs.js | 4 ++-- examples/acScripts/ControlledAC.js | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/examples/acScripts/ControlACs.js b/examples/acScripts/ControlACs.js index c0d5043e26..ba066d9750 100644 --- a/examples/acScripts/ControlACs.js +++ b/examples/acScripts/ControlACs.js @@ -190,7 +190,7 @@ function mousePressEvent(event) { sendCommand(i, STOP); } else if (loadIcon[i] === toolBars[i].clicked(clickedOverlay, false)) { input_text = Window.prompt("Insert the url of the clip: ",""); - if(!(input_text === "" || input_text === null)) { + if (!(input_text === "" || input_text === null)) { clip_url = input_text; sendCommand(i, LOAD); } @@ -211,7 +211,7 @@ function mousePressEvent(event) { sendCommand(i, STOP); } else if (loadIcon[i] === toolBars[i].clicked(clickedOverlay, false)) { input_text = Window.prompt("Insert the url of the clip: ",""); - if(!(input_text === "" || input_text === null)) { + if (!(input_text === "" || input_text === null)) { clip_url = input_text; sendCommand(i, LOAD); } diff --git a/examples/acScripts/ControlledAC.js b/examples/acScripts/ControlledAC.js index de31f66df7..41a8a2b257 100644 --- a/examples/acScripts/ControlledAC.js +++ b/examples/acScripts/ControlledAC.js @@ -66,12 +66,10 @@ function getAction(controlEntity) { var uD_action = userData.actionKey.uD_action; var uD_url = userData.clipKey.uD_url; - print("Sono " + id + " e ho ricevuto un comando da " + uD_id); - Entities.deleteEntity((Entities.getEntityProperties(controlEntity)).id); - if(uD_id === id || uD_id === -1) { - if(uD_action === 6) + if (uD_id === id || uD_id === -1) { + if (uD_action === 6) clip_url = uD_url; return uD_action; From 8c21ac144ee63642461e457bdcafcf0556ddf6db Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 13 Nov 2015 16:45:19 -0800 Subject: [PATCH 57/61] Fixing review comments --- interface/src/avatar/MyAvatar.cpp | 2 +- libraries/avatars/src/AvatarData.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 4d62946a5f..278cc5ff81 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -608,7 +608,7 @@ float MyAvatar::recorderElapsed() { if (!_recorder) { return 0; } - return (float)_recorder->position(); + return (float)_recorder->position() / (float) MSECS_PER_SECOND; } QMetaObject::Connection _audioClientRecorderConnection; diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index e44219977b..8537f37f84 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -1664,7 +1664,7 @@ void avatarStateFromFrame(const QByteArray& frameData, AvatarData* _avatar) { auto worldTransform = currentBasis->worldTransform(relativeTransform); _avatar->setPosition(worldTransform.getTranslation()); _avatar->setOrientation(worldTransform.getRotation()); - _avatar->setTargetScale(worldTransform.getScale().x); + // _avatar->setTargetScale(worldTransform.getScale().x); } From 89e5db11a016005e6b402cdd297ada002256d287 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 13 Nov 2015 17:41:41 -0800 Subject: [PATCH 58/61] More fixes --- examples/utilities/record/recorder.js | 13 +++++-------- libraries/avatars/src/AvatarData.cpp | 7 +++++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/utilities/record/recorder.js b/examples/utilities/record/recorder.js index b44cb23aa8..40476626e8 100644 --- a/examples/utilities/record/recorder.js +++ b/examples/utilities/record/recorder.js @@ -176,16 +176,13 @@ function formatTime(time) { var SEC_PER_MIN = 60; var MSEC_PER_SEC = 1000; - time = time * (MSEC_PER_SEC); + var hours = Math.floor(time / (SEC_PER_MIN * MIN_PER_HOUR)); + time -= hours * (SEC_PER_MIN * MIN_PER_HOUR); - var hours = Math.floor(time / (MSEC_PER_SEC * SEC_PER_MIN * MIN_PER_HOUR)); - time -= hours * (MSEC_PER_SEC * SEC_PER_MIN * MIN_PER_HOUR); + var minutes = Math.floor(time / (SEC_PER_MIN)); + time -= minutes * (SEC_PER_MIN); - var minutes = Math.floor(time / (MSEC_PER_SEC * SEC_PER_MIN)); - time -= minutes * (MSEC_PER_SEC * SEC_PER_MIN); - - var seconds = Math.floor(time / MSEC_PER_SEC); - seconds = time / MSEC_PER_SEC; + var seconds = time; var text = ""; text += (hours > 0) ? hours + ":" : diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 8537f37f84..a47d5f663e 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -1513,7 +1513,8 @@ void AvatarData::setRecordingBasis(std::shared_ptr recordingBasis) { recordingBasis = std::make_shared(); recordingBasis->setRotation(getOrientation()); recordingBasis->setTranslation(getPosition()); - recordingBasis->setScale(getTargetScale()); + // TODO: find a different way to record/playback the Scale of the avatar + //recordingBasis->setScale(getTargetScale()); } _recordingBasis = recordingBasis; } @@ -1664,7 +1665,9 @@ void avatarStateFromFrame(const QByteArray& frameData, AvatarData* _avatar) { auto worldTransform = currentBasis->worldTransform(relativeTransform); _avatar->setPosition(worldTransform.getTranslation()); _avatar->setOrientation(worldTransform.getRotation()); - // _avatar->setTargetScale(worldTransform.getScale().x); + + // TODO: find a way to record/playback the Scale of the avatar + //_avatar->setTargetScale(worldTransform.getScale().x); } From 245150333b949200a11bb40e8b1d840fe8e66353 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 13 Nov 2015 18:08:18 -0800 Subject: [PATCH 59/61] Fix for missing avatars on entry This should fix the issue where a persons avatar was occasionally not visible to others for a long period of time. This was due to several factors: 1) When a new avatar was added to the simulation that identity packet was not broadcast to other avatars on the server. This would rely on random logic to send the identity eventually. This is fixed in this PR, by sending identity packets to all other clients when a new clients arrive. 2) The random identity logic was not being executed if the sequence number check caused an update to be skipped. This means the probability of sending a random packet was reduced significantly, especially for clients that were loading geometry on entry. This was fixed by doing the random check before sequence number check. 3) The 1/300 probably used in the check was too low, this was only a 63% chance of sending a identity packet within 5 seconds. This was fixed by changing the probability to 1/187, which is a 80% chance to send an identity packet within 5 seconds. 4) The randFloat() implementation slightly reduced the identity packet probability due to quantization errors. This has been replaced by a C++ std random number generator. --- assignment-client/src/avatars/AvatarMixer.cpp | 101 +++++++++--------- .../src/avatars/AvatarMixerClientData.cpp | 14 ++- .../src/avatars/AvatarMixerClientData.h | 25 +++-- 3 files changed, 76 insertions(+), 64 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 0a455891f9..74641e9387 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -63,7 +63,9 @@ AvatarMixer::~AvatarMixer() { _broadcastThread.wait(); } -const float BILLBOARD_AND_IDENTITY_SEND_PROBABILITY = 1.0f / 300.0f; +// An 80% chance of sending a identity packet within a 5 second interval. +// assuming 60 htz update rate. +const float BILLBOARD_AND_IDENTITY_SEND_PROBABILITY = 1.0f / 187.0f; // NOTE: some additional optimizations to consider. // 1) use the view frustum to cull those avatars that are out of view. Since avatar data doesn't need to be present @@ -243,6 +245,47 @@ void AvatarMixer::broadcastAvatarData() { return; } + // if an avatar has just connected make sure we send out the mesh and billboard + bool forceSend = !nodeData->checkAndSetHasReceivedFirstPackets() + || !otherNodeData->checkAndSetHasReceivedFirstPacketsFrom(node->getUUID()); + + // we will also force a send of billboard or identity packet + // if either has changed in the last frame + if (otherNodeData->getBillboardChangeTimestamp() > 0 + && (forceSend + || otherNodeData->getBillboardChangeTimestamp() > _lastFrameTimestamp + || distribution(generator) < BILLBOARD_AND_IDENTITY_SEND_PROBABILITY)) { + + QByteArray rfcUUID = otherNode->getUUID().toRfc4122(); + QByteArray billboard = otherNodeData->getAvatar().getBillboard(); + + auto billboardPacket = NLPacket::create(PacketType::AvatarBillboard, rfcUUID.size() + billboard.size()); + billboardPacket->write(rfcUUID); + billboardPacket->write(billboard); + + nodeList->sendPacket(std::move(billboardPacket), *node); + + ++_sumBillboardPackets; + } + + if (otherNodeData->getIdentityChangeTimestamp() > 0 + && (forceSend + || otherNodeData->getIdentityChangeTimestamp() > _lastFrameTimestamp + || distribution(generator) < BILLBOARD_AND_IDENTITY_SEND_PROBABILITY)) { + + QByteArray individualData = otherNodeData->getAvatar().identityByteArray(); + + auto identityPacket = NLPacket::create(PacketType::AvatarIdentity, individualData.size()); + + individualData.replace(0, NUM_BYTES_RFC4122_UUID, otherNode->getUUID().toRfc4122()); + + identityPacket->write(individualData); + + nodeList->sendPacket(std::move(identityPacket), *node); + + ++_sumIdentityPackets; + } + AvatarData& otherAvatar = otherNodeData->getAvatar(); // Decide whether to send this avatar's data based on it's distance from us @@ -254,10 +297,10 @@ void AvatarMixer::broadcastAvatarData() { // potentially update the max full rate distance for this frame maxAvatarDistanceThisFrame = std::max(maxAvatarDistanceThisFrame, distanceToAvatar); - if (distanceToAvatar != 0.0f + if (distanceToAvatar != 0.0f && distribution(generator) > (nodeData->getFullRateDistance() / distanceToAvatar)) { - return; - } + return; + } AvatarDataSequenceNumber lastSeqToReceiver = nodeData->getLastBroadcastSequenceNumber(otherNode->getUUID()); AvatarDataSequenceNumber lastSeqFromSender = otherNodeData->getLastReceivedSequenceNumber(); @@ -291,53 +334,11 @@ void AvatarMixer::broadcastAvatarData() { numAvatarDataBytes += avatarPacketList->write(otherNode->getUUID().toRfc4122()); numAvatarDataBytes += - avatarPacketList->write(otherAvatar.toByteArray(false, randFloat() < AVATAR_SEND_FULL_UPDATE_RATIO)); + avatarPacketList->write(otherAvatar.toByteArray(false, distribution(generator) < AVATAR_SEND_FULL_UPDATE_RATIO)); avatarPacketList->endSegment(); - - // if the receiving avatar has just connected make sure we send out the mesh and billboard - // for this avatar (assuming they exist) - bool forceSend = !nodeData->checkAndSetHasReceivedFirstPackets(); - - // we will also force a send of billboard or identity packet - // if either has changed in the last frame - - if (otherNodeData->getBillboardChangeTimestamp() > 0 - && (forceSend - || otherNodeData->getBillboardChangeTimestamp() > _lastFrameTimestamp - || randFloat() < BILLBOARD_AND_IDENTITY_SEND_PROBABILITY)) { - - QByteArray rfcUUID = otherNode->getUUID().toRfc4122(); - QByteArray billboard = otherNodeData->getAvatar().getBillboard(); - - auto billboardPacket = NLPacket::create(PacketType::AvatarBillboard, rfcUUID.size() + billboard.size()); - billboardPacket->write(rfcUUID); - billboardPacket->write(billboard); - - nodeList->sendPacket(std::move(billboardPacket), *node); - - ++_sumBillboardPackets; - } - - if (otherNodeData->getIdentityChangeTimestamp() > 0 - && (forceSend - || otherNodeData->getIdentityChangeTimestamp() > _lastFrameTimestamp - || randFloat() < BILLBOARD_AND_IDENTITY_SEND_PROBABILITY)) { - - QByteArray individualData = otherNodeData->getAvatar().identityByteArray(); - - auto identityPacket = NLPacket::create(PacketType::AvatarIdentity, individualData.size()); - - individualData.replace(0, NUM_BYTES_RFC4122_UUID, otherNode->getUUID().toRfc4122()); - - identityPacket->write(individualData); - - nodeList->sendPacket(std::move(identityPacket), *node); - - ++_sumIdentityPackets; - } }); - + // close the current packet so that we're always sending something avatarPacketList->closeCurrentPacket(true); @@ -484,7 +485,7 @@ void AvatarMixer::sendStatsPacket() { // add the key to ask the domain-server for a username replacement, if it has it avatarStats[USERNAME_UUID_REPLACEMENT_STATS_KEY] = uuidStringWithoutCurlyBraces(node->getUUID()); - + avatarStats[NODE_OUTBOUND_KBPS_STAT_KEY] = node->getOutboundBandwidth(); avatarStats[NODE_INBOUND_KBPS_STAT_KEY] = node->getInboundBandwidth(); @@ -537,7 +538,7 @@ void AvatarMixer::run() { qDebug() << "Waiting for domain settings from domain-server."; // block until we get the settingsRequestComplete signal - + QEventLoop loop; connect(&domainHandler, &DomainHandler::settingsReceived, &loop, &QEventLoop::quit); connect(&domainHandler, &DomainHandler::settingsReceiveFail, &loop, &QEventLoop::quit); diff --git a/assignment-client/src/avatars/AvatarMixerClientData.cpp b/assignment-client/src/avatars/AvatarMixerClientData.cpp index 0a9be20691..bfa7b99b68 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.cpp +++ b/assignment-client/src/avatars/AvatarMixerClientData.cpp @@ -16,7 +16,7 @@ int AvatarMixerClientData::parseData(NLPacket& packet) { // pull the sequence number from the data first packet.readPrimitive(&_lastReceivedSequenceNumber); - + // compute the offset to the data payload return _avatar.parseDataFromBuffer(packet.readWithoutCopy(packet.bytesLeftToRead())); } @@ -27,6 +27,14 @@ bool AvatarMixerClientData::checkAndSetHasReceivedFirstPackets() { return oldValue; } +bool AvatarMixerClientData::checkAndSetHasReceivedFirstPacketsFrom(const QUuid& uuid) { + if (_hasReceivedFirstPacketsFrom.find(uuid) == _hasReceivedFirstPacketsFrom.end()) { + _hasReceivedFirstPacketsFrom.insert(uuid); + return false; + } + return true; +} + uint16_t AvatarMixerClientData::getLastBroadcastSequenceNumber(const QUuid& nodeUUID) const { // return the matching PacketSequenceNumber, or the default if we don't have it auto nodeMatch = _lastBroadcastSequenceNumbers.find(nodeUUID); @@ -45,9 +53,9 @@ void AvatarMixerClientData::loadJSONStats(QJsonObject& jsonObject) const { jsonObject["avg_other_av_starves_per_second"] = getAvgNumOtherAvatarStarvesPerSecond(); jsonObject["avg_other_av_skips_per_second"] = getAvgNumOtherAvatarSkipsPerSecond(); jsonObject["total_num_out_of_order_sends"] = _numOutOfOrderSends; - + jsonObject[OUTBOUND_AVATAR_DATA_STATS_KEY] = getOutboundAvatarDataKbps(); jsonObject[INBOUND_AVATAR_DATA_STATS_KEY] = _avatar.getAverageBytesReceivedPerSecond() / (float) BYTES_PER_KILOBIT; - + jsonObject["av_data_receive_rate"] = _avatar.getReceiveRate(); } diff --git a/assignment-client/src/avatars/AvatarMixerClientData.h b/assignment-client/src/avatars/AvatarMixerClientData.h index e68a54c265..42a2c1d4e4 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.h +++ b/assignment-client/src/avatars/AvatarMixerClientData.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -34,25 +35,26 @@ class AvatarMixerClientData : public NodeData { public: int parseData(NLPacket& packet); AvatarData& getAvatar() { return _avatar; } - + bool checkAndSetHasReceivedFirstPackets(); + bool checkAndSetHasReceivedFirstPacketsFrom(const QUuid& uuid); uint16_t getLastBroadcastSequenceNumber(const QUuid& nodeUUID) const; void setLastBroadcastSequenceNumber(const QUuid& nodeUUID, uint16_t sequenceNumber) { _lastBroadcastSequenceNumbers[nodeUUID] = sequenceNumber; } Q_INVOKABLE void removeLastBroadcastSequenceNumber(const QUuid& nodeUUID) { _lastBroadcastSequenceNumbers.erase(nodeUUID); } - + uint16_t getLastReceivedSequenceNumber() const { return _lastReceivedSequenceNumber; } quint64 getBillboardChangeTimestamp() const { return _billboardChangeTimestamp; } void setBillboardChangeTimestamp(quint64 billboardChangeTimestamp) { _billboardChangeTimestamp = billboardChangeTimestamp; } - + quint64 getIdentityChangeTimestamp() const { return _identityChangeTimestamp; } void setIdentityChangeTimestamp(quint64 identityChangeTimestamp) { _identityChangeTimestamp = identityChangeTimestamp; } - + void setFullRateDistance(float fullRateDistance) { _fullRateDistance = fullRateDistance; } float getFullRateDistance() const { return _fullRateDistance; } - + void setMaxAvatarDistance(float maxAvatarDistance) { _maxAvatarDistance = maxAvatarDistance; } float getMaxAvatarDistance() const { return _maxAvatarDistance; } @@ -73,31 +75,32 @@ public: void resetNumFramesSinceFRDAdjustment() { _numFramesSinceAdjustment = 0; } void recordSentAvatarData(int numBytes) { _avgOtherAvatarDataRate.updateAverage((float) numBytes); } - + float getOutboundAvatarDataKbps() const { return _avgOtherAvatarDataRate.getAverageSampleValuePerSecond() / (float) BYTES_PER_KILOBIT; } - + void loadJSONStats(QJsonObject& jsonObject) const; private: AvatarData _avatar; - + uint16_t _lastReceivedSequenceNumber { 0 }; std::unordered_map _lastBroadcastSequenceNumbers; + std::unordered_set _hasReceivedFirstPacketsFrom; bool _hasReceivedFirstPackets = false; quint64 _billboardChangeTimestamp = 0; quint64 _identityChangeTimestamp = 0; - + float _fullRateDistance = FLT_MAX; float _maxAvatarDistance = FLT_MAX; - + int _numAvatarsSentLastFrame = 0; int _numFramesSinceAdjustment = 0; SimpleMovingAverage _otherAvatarStarves; SimpleMovingAverage _otherAvatarSkips; int _numOutOfOrderSends = 0; - + SimpleMovingAverage _avgOtherAvatarDataRate; }; From 7aefc5c9f705b42674e9a26d07704fb377626fff Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 16 Nov 2015 10:14:28 -0800 Subject: [PATCH 60/61] AvatarMixer: remove redundant identity packet send Removed AvatarClientData::checkAndSetHasReceivedFirstPackets boolean. This is handled by the AvatarClientData::checkAndSetHasReceivedFirstPacketsFrom set. --- assignment-client/src/avatars/AvatarMixer.cpp | 5 ++--- assignment-client/src/avatars/AvatarMixerClientData.cpp | 6 ------ assignment-client/src/avatars/AvatarMixerClientData.h | 2 -- 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 74641e9387..1e17467c3b 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -245,9 +245,8 @@ void AvatarMixer::broadcastAvatarData() { return; } - // if an avatar has just connected make sure we send out the mesh and billboard - bool forceSend = !nodeData->checkAndSetHasReceivedFirstPackets() - || !otherNodeData->checkAndSetHasReceivedFirstPacketsFrom(node->getUUID()); + // make sure we send out identity and billboard packets to and from new arrivals. + bool forceSend = !otherNodeData->checkAndSetHasReceivedFirstPacketsFrom(node->getUUID()); // we will also force a send of billboard or identity packet // if either has changed in the last frame diff --git a/assignment-client/src/avatars/AvatarMixerClientData.cpp b/assignment-client/src/avatars/AvatarMixerClientData.cpp index bfa7b99b68..9d78d92463 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.cpp +++ b/assignment-client/src/avatars/AvatarMixerClientData.cpp @@ -21,12 +21,6 @@ int AvatarMixerClientData::parseData(NLPacket& packet) { return _avatar.parseDataFromBuffer(packet.readWithoutCopy(packet.bytesLeftToRead())); } -bool AvatarMixerClientData::checkAndSetHasReceivedFirstPackets() { - bool oldValue = _hasReceivedFirstPackets; - _hasReceivedFirstPackets = true; - return oldValue; -} - bool AvatarMixerClientData::checkAndSetHasReceivedFirstPacketsFrom(const QUuid& uuid) { if (_hasReceivedFirstPacketsFrom.find(uuid) == _hasReceivedFirstPacketsFrom.end()) { _hasReceivedFirstPacketsFrom.insert(uuid); diff --git a/assignment-client/src/avatars/AvatarMixerClientData.h b/assignment-client/src/avatars/AvatarMixerClientData.h index 42a2c1d4e4..1f5e8fa77a 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.h +++ b/assignment-client/src/avatars/AvatarMixerClientData.h @@ -36,7 +36,6 @@ public: int parseData(NLPacket& packet); AvatarData& getAvatar() { return _avatar; } - bool checkAndSetHasReceivedFirstPackets(); bool checkAndSetHasReceivedFirstPacketsFrom(const QUuid& uuid); uint16_t getLastBroadcastSequenceNumber(const QUuid& nodeUUID) const; @@ -87,7 +86,6 @@ private: std::unordered_map _lastBroadcastSequenceNumbers; std::unordered_set _hasReceivedFirstPacketsFrom; - bool _hasReceivedFirstPackets = false; quint64 _billboardChangeTimestamp = 0; quint64 _identityChangeTimestamp = 0; From 584e35e4ab1e4fb8d28d71533bbee3b9da84a2cd Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 16 Nov 2015 10:58:11 -0800 Subject: [PATCH 61/61] have killNodeWithUUID return success to avoid double lookup --- domain-server/src/DomainServer.cpp | 4 +--- libraries/networking/src/LimitedNodeList.cpp | 5 ++++- libraries/networking/src/LimitedNodeList.h | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 790548c5b3..127c121cf3 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -1836,9 +1836,7 @@ void DomainServer::processNodeDisconnectRequestPacket(QSharedPointer p qDebug() << "Received a disconnect request from node with UUID" << nodeUUID; - if (limitedNodeList->nodeWithUUID(nodeUUID)) { - limitedNodeList->killNodeWithUUID(nodeUUID); - + if (limitedNodeList->killNodeWithUUID(nodeUUID)) { static auto removedNodePacket = NLPacket::create(PacketType::DomainServerRemovedNode, NUM_BYTES_RFC4122_UUID); removedNodePacket->reset(); diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 75d42f55cb..fdb5049f00 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -441,7 +441,7 @@ void LimitedNodeList::reset() { _nodeSocket.clearConnections(); } -void LimitedNodeList::killNodeWithUUID(const QUuid& nodeUUID) { +bool LimitedNodeList::killNodeWithUUID(const QUuid& nodeUUID) { QReadLocker readLocker(&_nodeMutex); NodeHash::iterator it = _nodeHash.find(nodeUUID); @@ -456,7 +456,10 @@ void LimitedNodeList::killNodeWithUUID(const QUuid& nodeUUID) { } handleNodeKill(matchingNode); + return true; } + + return false; } void LimitedNodeList::processKillNode(NLPacket& packet) { diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 2488b0cf8c..1aacd27572 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -230,7 +230,7 @@ public slots: virtual void sendSTUNRequest(); void sendPingPackets(); - void killNodeWithUUID(const QUuid& nodeUUID); + bool killNodeWithUUID(const QUuid& nodeUUID); signals: void dataSent(quint8 channelType, int bytes);