diff --git a/examples/count.js b/examples/count.js new file mode 100644 index 0000000000..917bec342d --- /dev/null +++ b/examples/count.js @@ -0,0 +1,26 @@ +// +// count.js +// hifi +// +// Created by Brad Hefta-Gaub on 12/31/13. +// Copyright (c) 2013 HighFidelity, Inc. All rights reserved. +// +// This is an example script that runs in a loop and displays a counter to the log +// + +var count = 0; + +function displayCount() { + print("count =" + count); + count++; +} + +function scriptEnding() { + print("SCRIPT ENDNG!!!\n"); +} + +// register the call back so it fires before each data send +Agent.willSendVisualDataCallback.connect(displayCount); + +// register our scriptEnding callback +Agent.scriptEnding.connect(scriptEnding); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 64c883b7f6..229cedf55c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2006,7 +2006,7 @@ void Application::updateAvatars(float deltaTime, glm::vec3 mouseRayOrigin, glm:: PerformanceWarning warn(showWarnings, "Application::updateAvatars()"); foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { - QMutexLocker(&node->getMutex()); + QMutexLocker locker(&node->getMutex()); if (node->getLinkedData()) { Avatar *avatar = (Avatar *)node->getLinkedData(); if (!avatar->isInitialized()) { @@ -3659,7 +3659,7 @@ void Application::renderAvatars(bool forceRenderHead, bool selfAvatarOnly) { NodeList* nodeList = NodeList::getInstance(); foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { - QMutexLocker(&node->getMutex()); + QMutexLocker locker(&node->getMutex()); if (node->getLinkedData() != NULL && node->getType() == NODE_TYPE_AGENT) { Avatar *avatar = (Avatar *)node->getLinkedData(); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 3c5fdb243f..d10cd1b17d 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -175,8 +175,6 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { // Compute instantaneous acceleration float forwardAcceleration = glm::length(glm::dot(getBodyFrontDirection(), getVelocity() - oldVelocity)) / deltaTime; - const float ACCELERATION_PITCH_DECAY = 0.4f; - const float ACCELERATION_PULL_THRESHOLD = 0.2f; const float OCULUS_ACCELERATION_PULL_THRESHOLD = 1.0f; const int OCULUS_YAW_OFFSET_THRESHOLD = 10; @@ -475,14 +473,19 @@ void MyAvatar::loadData(QSettings* settings) { } void MyAvatar::orbit(const glm::vec3& position, int deltaX, int deltaY) { - glm::vec3 vector = getPosition() - position; + // first orbit horizontally glm::quat orientation = getOrientation(); - glm::vec3 up = orientation * IDENTITY_UP; const float ANGULAR_SCALE = 0.5f; - glm::quat rotation = glm::angleAxis(deltaX * -ANGULAR_SCALE, up); - const float LINEAR_SCALE = 0.01f; - setPosition(position + rotation * vector + up * (deltaY * LINEAR_SCALE * _scale)); - setOrientation(rotation * orientation); + glm::quat rotation = glm::angleAxis(deltaX * -ANGULAR_SCALE, orientation * IDENTITY_UP); + setPosition(position + rotation * (getPosition() - position)); + orientation = rotation * orientation; + setOrientation(orientation); + + // then vertically + float oldMousePitch = _head.getMousePitch(); + _head.setMousePitch(oldMousePitch + deltaY * -ANGULAR_SCALE); + rotation = glm::angleAxis(_head.getMousePitch() - oldMousePitch, orientation * IDENTITY_RIGHT); + setPosition(position + rotation * (getPosition() - position)); } float MyAvatar::getAbsoluteHeadYaw() const { diff --git a/libraries/octree/src/JurisdictionListener.cpp b/libraries/octree/src/JurisdictionListener.cpp index ae27259f83..d8919ac48e 100644 --- a/libraries/octree/src/JurisdictionListener.cpp +++ b/libraries/octree/src/JurisdictionListener.cpp @@ -20,12 +20,9 @@ JurisdictionListener::JurisdictionListener(NODE_TYPE type, PacketSenderNotify* n { _nodeType = type; ReceivedPacketProcessor::_dontSleep = true; // we handle sleeping so this class doesn't need to - NodeList* nodeList = NodeList::getInstance(); - connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), SLOT(nodeKilled(SharedNodePointer))); - - //qDebug("JurisdictionListener::JurisdictionListener(NODE_TYPE type=%c)\n", type); - +// connect(nodeList, &NodeList::nodeKilled, this, &JurisdictionListener::nodeKilled); +// qDebug("JurisdictionListener::JurisdictionListener(NODE_TYPE type=%c)\n", type); } void JurisdictionListener::nodeKilled(SharedNodePointer node) { diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index db486f9bb9..6b85cf33ad 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -51,11 +51,12 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, bool wantMenuItems, if (scriptMenuName) { _scriptMenuName = "Stop "; _scriptMenuName.append(scriptMenuName); + _scriptMenuName.append(QString(" [%1]").arg(_scriptNumber)); } else { _scriptMenuName = "Stop Script "; - _scriptNumber++; _scriptMenuName.append(_scriptNumber); } + _scriptNumber++; _menu = menu; _controllerScriptingInterface = controllerScriptingInterface; } @@ -224,6 +225,7 @@ void ScriptEngine::run() { qDebug() << "Uncaught exception at line" << line << ":" << _engine.uncaughtException().toString(); } } + emit scriptEnding(); cleanMenuItems(); // If we were on a thread, then wait till it's done diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 842b902fcf..06597f82a8 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -57,7 +57,9 @@ public slots: signals: void willSendAudioDataCallback(); void willSendVisualDataCallback(); + void scriptEnding(); void finished(); + protected: QString _scriptContents; bool _isFinished; diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 06d2bbe05b..f33137a092 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -56,6 +56,7 @@ NodeList* NodeList::getInstance() { NodeList::NodeList(char newOwnerType, unsigned short int newSocketListenPort) : _nodeHash(), + _nodeHashMutex(), _domainHostname(DEFAULT_DOMAIN_HOSTNAME), _domainSockAddr(HifiSockAddr(QHostAddress::Null, DEFAULT_DOMAIN_SERVER_PORT)), _nodeSocket(), @@ -230,7 +231,7 @@ void NodeList::processBulkNodeData(const HifiSockAddr& senderAddress, unsigned c } int NodeList::updateNodeWithData(Node *node, const HifiSockAddr& senderSockAddr, unsigned char *packetData, int dataBytes) { - QMutexLocker(&node->getMutex()); + QMutexLocker locker(&node->getMutex()); node->setLastHeardMicrostamp(usecTimestampNow()); @@ -266,19 +267,25 @@ SharedNodePointer NodeList::nodeWithAddress(const HifiSockAddr &senderSockAddr) } SharedNodePointer NodeList::nodeWithUUID(const QUuid& nodeUUID) { + QMutexLocker locker(&_nodeHashMutex); return _nodeHash.value(nodeUUID); } +NodeHash NodeList::getNodeHash() { + QMutexLocker locker(&_nodeHashMutex); + return NodeHash(_nodeHash); +} + void NodeList::clear() { qDebug() << "Clearing the NodeList. Deleting all nodes in list."; + + QMutexLocker locker(&_nodeHashMutex); NodeHash::iterator nodeItem = _nodeHash.begin(); // iterate the nodes in the list while (nodeItem != _nodeHash.end()) { - NodeHash::iterator previousNodeItem = nodeItem; - ++nodeItem; - killNodeAtHashIterator(previousNodeItem); + nodeItem = killNodeAtHashIterator(nodeItem); } } @@ -438,16 +445,18 @@ void NodeList::processSTUNResponse(unsigned char* packetData, size_t dataBytes) } void NodeList::killNodeWithUUID(const QUuid& nodeUUID) { + QMutexLocker locker(&_nodeHashMutex); + NodeHash::iterator nodeItemToKill = _nodeHash.find(nodeUUID); if (nodeItemToKill != _nodeHash.end()) { killNodeAtHashIterator(nodeItemToKill); } } -void NodeList::killNodeAtHashIterator(NodeHash::iterator& nodeItemToKill) { +NodeHash::iterator NodeList::killNodeAtHashIterator(NodeHash::iterator& nodeItemToKill) { qDebug() << "Killed" << *nodeItemToKill.value(); emit nodeKilled(nodeItemToKill.value()); - _nodeHash.erase(nodeItemToKill); + return _nodeHash.erase(nodeItemToKill); } void NodeList::sendKillNode(const char* nodeTypes, int numNodeTypes) { @@ -674,6 +683,8 @@ void NodeList::pingPublicAndLocalSocketsForInactiveNode(Node* node) { SharedNodePointer NodeList::addOrUpdateNode(const QUuid& uuid, char nodeType, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket) { + _nodeHashMutex.lock(); + SharedNodePointer matchingNode = _nodeHash.value(uuid); if (!matchingNode) { @@ -683,13 +694,17 @@ SharedNodePointer NodeList::addOrUpdateNode(const QUuid& uuid, char nodeType, _nodeHash.insert(newNode->getUUID(), newNodeSharedPointer); + _nodeHashMutex.unlock(); + qDebug() << "Added" << *newNode; emit nodeAdded(newNodeSharedPointer); return newNodeSharedPointer; } else { - QMutexLocker(&matchingNode->getMutex()); + _nodeHashMutex.unlock(); + + QMutexLocker locker(&matchingNode->getMutex()); if (matchingNode->getType() == NODE_TYPE_AUDIO_MIXER || matchingNode->getType() == NODE_TYPE_VOXEL_SERVER || @@ -781,24 +796,27 @@ SharedNodePointer NodeList::soloNodeOfType(char nodeType) { void NodeList::removeSilentNodes() { + _nodeHashMutex.lock(); + NodeHash::iterator nodeItem = _nodeHash.begin(); while (nodeItem != _nodeHash.end()) { SharedNodePointer node = nodeItem.value(); - QMutexLocker(&node->getMutex()); + node->getMutex().lock(); if ((usecTimestampNow() - node->getLastHeardMicrostamp()) > NODE_SILENCE_THRESHOLD_USECS) { // call our private method to kill this node (removes it and emits the right signal) - NodeHash::iterator previousNodeItem = nodeItem; - ++nodeItem; - - killNodeAtHashIterator(previousNodeItem); + nodeItem = killNodeAtHashIterator(nodeItem); } else { // we didn't kill this node, push the iterator forwards ++nodeItem; } + + node->getMutex().unlock(); } + + _nodeHashMutex.unlock(); } const QString QSETTINGS_GROUP_NAME = "NodeList"; diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index 391e329200..b5e27564b1 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -21,6 +21,7 @@ #include // not on windows, not needed for mac or windows #endif +#include #include #include #include @@ -81,7 +82,7 @@ public: void(*linkedDataCreateCallback)(Node *); - const NodeHash& getNodeHash() { return _nodeHash; } + NodeHash getNodeHash(); int size() const { return _nodeHash.size(); } int getNumNoReplyDomainCheckIns() const { return _numNoReplyDomainCheckIns; } @@ -140,9 +141,10 @@ private: void processSTUNResponse(unsigned char* packetData, size_t dataBytes); void processKillNode(unsigned char* packetData, size_t dataBytes); - void killNodeAtHashIterator(NodeHash::iterator& nodeItemToKill); + NodeHash::iterator killNodeAtHashIterator(NodeHash::iterator& nodeItemToKill); NodeHash _nodeHash; + QMutex _nodeHashMutex; QString _domainHostname; HifiSockAddr _domainSockAddr; QUdpSocket _nodeSocket;