From 14b7f58fef60052c1a8cac69d22a74568faf38aa Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 5 Aug 2013 13:47:18 -0700 Subject: [PATCH] Kills local voxels if voxel server is removed from NodeList - added notification hooks to NodeList - implemented hooks in VoxelSystem to kill local voxels when voxel server is killed --- interface/src/Application.cpp | 7 +++++++ interface/src/Application.h | 1 + interface/src/VoxelSystem.cpp | 32 +++++++++++++++++++++++++++++-- interface/src/VoxelSystem.h | 5 ++++- libraries/shared/src/NodeList.cpp | 31 +++++++++++++++++++++++++++++- libraries/shared/src/NodeList.h | 16 ++++++++++++++++ 6 files changed, 88 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a3bd6c4718..2dfd51bc98 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -234,6 +234,9 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : NodeList::createInstance(NODE_TYPE_AGENT, listenPort); + NodeList::getInstance()->addHook(&_voxels); + + _enableNetworkThread = !cmdOptionExists(argc, constArgv, "--nonblocking"); if (!_enableNetworkThread) { NodeList::getInstance()->getNodeSocket()->setBlocking(false); @@ -317,6 +320,10 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : // initialization continues in initializeGL when OpenGL context is ready } +Application::~Application() { + NodeList::getInstance()->removeHook(&_voxels); +} + void Application::initializeGL() { qDebug( "Created Display Window.\n" ); diff --git a/interface/src/Application.h b/interface/src/Application.h index 4745196bf4..9a71365c5a 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -66,6 +66,7 @@ public: static Application* getInstance() { return static_cast(QCoreApplication::instance()); } Application(int& argc, char** argv, timeval &startup_time); + ~Application(); void initializeGL(); void paintGL(); diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 65d819eddc..72f1977ad6 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -1553,10 +1553,38 @@ void VoxelSystem::falseColorizeOccludedV2() { VoxelProjectedPolygon::intersects_calls ); //myCoverageMapV2.erase(); - - _tree->setDirtyBit(); setupNewVoxelsForDrawing(); } +void VoxelSystem::nodeAdded(Node* node) { + if (node->getType() == NODE_TYPE_VOXEL_SERVER) { + uint16_t nodeID = node->getNodeID(); + //printf("VoxelSystem... voxel server %u added...\n", nodeID); + } +} + +bool VoxelSystem::killSourceVoxelsOperation(VoxelNode* node, void* extraData) { + uint16_t killedNodeID = *(uint16_t*)extraData; + for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { + VoxelNode* childNode = node->getChildAtIndex(i); + if (childNode && childNode->getSourceID()== killedNodeID) { + node->safeDeepDeleteChildAtIndex(i); + } + } + return true; +} + +void VoxelSystem::nodeKilled(Node* node) { + if (node->getType() == NODE_TYPE_VOXEL_SERVER) { + uint16_t nodeID = node->getNodeID(); + //printf("VoxelSystem... voxel server %u removed...\n", nodeID); + + // Kill any voxels from the local tree + _tree->recurseTreeWithOperation(killSourceVoxelsOperation, &nodeID); + _tree->setDirtyBit(); + setupNewVoxelsForDrawing(); + } +} + diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 6c6bf261f9..5296d1a242 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -28,7 +28,7 @@ class ProgramObject; const int NUM_CHILDREN = 8; -class VoxelSystem : public NodeData, public VoxelNodeDeleteHook { +class VoxelSystem : public NodeData, public VoxelNodeDeleteHook, public NodeListHook { public: VoxelSystem(float treeScale = TREE_SCALE, int maxVoxels = MAX_VOXELS_PER_SYSTEM); ~VoxelSystem(); @@ -99,6 +99,8 @@ public: CoverageMap myCoverageMap; virtual void nodeDeleted(VoxelNode* node); + virtual void nodeAdded(Node* node); + virtual void nodeKilled(Node* node); protected: float _treeScale; @@ -140,6 +142,7 @@ private: static bool falseColorizeSubTreeOperation(VoxelNode* node, void* extraData); static bool falseColorizeOccludedV2Operation(VoxelNode* node, void* extraData); static bool falseColorizeBySourceOperation(VoxelNode* node, void* extraData); + static bool killSourceVoxelsOperation(VoxelNode* node, void* extraData); int updateNodeInArraysAsFullVBO(VoxelNode* node); int updateNodeInArraysAsPartialVBO(VoxelNode* node); diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 2dfd537d93..2ca07660e2 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -435,6 +435,8 @@ void NodeList::addNodeToList(Node* newNode) { ++_numNodes; qDebug() << "Added" << *newNode << "\n"; + + notifyHooksOfAddedNode(newNode); } unsigned NodeList::broadcastToNodes(unsigned char *broadcastData, size_t dataBytes, const char* nodeTypes, int numNodeTypes) { @@ -476,7 +478,7 @@ Node* NodeList::soloNodeOfType(char nodeType) { return NULL; } -void *removeSilentNodes(void *args) { +void* removeSilentNodes(void *args) { NodeList* nodeList = (NodeList*) args; uint64_t checkTimeUSecs; int sleepTime; @@ -490,6 +492,8 @@ void *removeSilentNodes(void *args) { qDebug() << "Killed" << *node << "\n"; + nodeList->notifyHooksOfKilledNode(&*node); + node->setAlive(false); } } @@ -619,3 +623,28 @@ void NodeListIterator::skipDeadAndStopIncrement() { } } } + +void NodeList::addHook(NodeListHook* hook) { + _hooks.push_back(hook); +} + +void NodeList::removeHook(NodeListHook* hook) { + for (int i = 0; i < _hooks.size(); i++) { + if (_hooks[i] == hook) { + _hooks.erase(_hooks.begin() + i); + return; + } + } +} + +void NodeList::notifyHooksOfAddedNode(Node* node) { + for (int i = 0; i < _hooks.size(); i++) { + _hooks[i]->nodeAdded(node); + } +} + +void NodeList::notifyHooksOfKilledNode(Node* node) { + for (int i = 0; i < _hooks.size(); i++) { + _hooks[i]->nodeKilled(node); + } +} diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index 260fddf96f..804717dc66 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -45,6 +45,14 @@ const int UNKNOWN_NODE_ID = -1; class NodeListIterator; +// Callers who want to hook add/kill callbacks should implement this class +class NodeListHook { +public: + virtual void nodeAdded(Node* node) = 0; + virtual void nodeKilled(Node* node) = 0; +}; + + class NodeList { public: static NodeList* createInstance(char ownerType, unsigned int socketListenPort = NODE_SOCKET_LISTEN_PORT); @@ -111,6 +119,12 @@ public: void saveData(QSettings* settings); friend class NodeListIterator; + + void addHook(NodeListHook* hook); + void removeHook(NodeListHook* hook); + void notifyHooksOfAddedNode(Node* node); + void notifyHooksOfKilledNode(Node* node); + private: static NodeList* _sharedInstance; @@ -136,6 +150,8 @@ private: void handlePingReply(sockaddr *nodeAddress); void timePingReply(sockaddr *nodeAddress, unsigned char *packetData); + + std::vector _hooks; }; class NodeListIterator : public std::iterator {