From 163d65d784bfc61c84d0a350829729daf0f785b3 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 5 Jan 2017 12:09:34 -0800 Subject: [PATCH 001/114] Setup basic EntityScriptServer --- assignment-client/src/Agent.cpp | 3 +- assignment-client/src/AssignmentFactory.cpp | 7 ++- .../src/scripts/EntityScriptServer.cpp | 17 ++++++++ .../src/scripts/EntityScriptServer.h | 43 +++++++++++++++++++ domain-server/src/DomainGatekeeper.cpp | 9 ++-- libraries/networking/src/Assignment.cpp | 4 ++ libraries/networking/src/Assignment.h | 2 +- libraries/networking/src/Node.cpp | 1 + libraries/networking/src/NodeType.h | 1 + 9 files changed, 78 insertions(+), 9 deletions(-) create mode 100644 assignment-client/src/scripts/EntityScriptServer.cpp create mode 100644 assignment-client/src/scripts/EntityScriptServer.h diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index e79085244f..d13b708837 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "Agent.h" + #include #include #include @@ -46,7 +48,6 @@ #include "RecordingScriptingInterface.h" #include "AbstractAudioInterface.h" -#include "Agent.h" #include "AvatarAudioTimer.h" static const int RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES = 10; diff --git a/assignment-client/src/AssignmentFactory.cpp b/assignment-client/src/AssignmentFactory.cpp index 75d474f566..38eb72649f 100644 --- a/assignment-client/src/AssignmentFactory.cpp +++ b/assignment-client/src/AssignmentFactory.cpp @@ -12,12 +12,13 @@ #include #include "Agent.h" +#include "assets/AssetServer.h" #include "AssignmentFactory.h" #include "audio/AudioMixer.h" #include "avatars/AvatarMixer.h" #include "entities/EntityServer.h" -#include "assets/AssetServer.h" #include "messages/MessagesMixer.h" +#include "scripts/EntityScriptServer.h" ThreadedAssignment* AssignmentFactory::unpackAssignment(ReceivedMessage& message) { @@ -39,7 +40,9 @@ ThreadedAssignment* AssignmentFactory::unpackAssignment(ReceivedMessage& message return new AssetServer(message); case Assignment::MessagesMixerType: return new MessagesMixer(message); + case Assignment::EntityScriptServerType: + return new EntityScriptServer(message); default: - return NULL; + return nullptr; } } diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp new file mode 100644 index 0000000000..66d1aa579d --- /dev/null +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -0,0 +1,17 @@ +// +// EntityScriptServer.cpp +// assignment-client/src/scripts +// +// Created by Clément Brisset on 1/5/17. +// Copyright 2013 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 "EntityScriptServer.h" + +EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : ThreadedAssignment(message) { + + +} diff --git a/assignment-client/src/scripts/EntityScriptServer.h b/assignment-client/src/scripts/EntityScriptServer.h new file mode 100644 index 0000000000..842f3802cf --- /dev/null +++ b/assignment-client/src/scripts/EntityScriptServer.h @@ -0,0 +1,43 @@ +// +// EntityScriptServer.h +// assignment-client/src/scripts +// +// Created by Clément Brisset on 1/5/17. +// Copyright 2013 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_EntityScriptServer_h +#define hifi_EntityScriptServer_h + +#include + +#include + + +class EntityScriptServer : public ThreadedAssignment { + Q_OBJECT + +public: + EntityScriptServer(ReceivedMessage& message); + +public slots: + void run() override; + void nodeActivated(SharedNodePointer activatedNode); + void nodeKilled(SharedNodePointer killedNode); + void sendStatsPacket() override; + +private slots: + void handleAudioPacket(QSharedPointer message); + void handleOctreePacket(QSharedPointer message, SharedNodePointer senderNode); + void handleJurisdictionPacket(QSharedPointer message, SharedNodePointer senderNode); + void handleSelectedAudioFormat(QSharedPointer message); + +private: + + +}; + +#endif // hifi_EntityScriptServer_h diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index 97f3e1a697..99bfd52cb6 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -46,10 +46,9 @@ QUuid DomainGatekeeper::assignmentUUIDForPendingAssignment(const QUuid& tempUUID } } -const NodeSet STATICALLY_ASSIGNED_NODES = NodeSet() << NodeType::AudioMixer - << NodeType::AvatarMixer << NodeType::EntityServer - << NodeType::AssetServer - << NodeType::MessagesMixer; +const NodeSet STATICALLY_ASSIGNED_NODES = NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer + << NodeType::EntityServer << NodeType::AssetServer << NodeType::MessagesMixer + << NodeType::EntityScriptServer; void DomainGatekeeper::processConnectRequestPacket(QSharedPointer message) { if (message->getSize() == 0) { @@ -72,7 +71,7 @@ void DomainGatekeeper::processConnectRequestPacket(QSharedPointer Date: Thu, 5 Jan 2017 14:46:16 -0800 Subject: [PATCH 002/114] More EntityScriptServer work --- assignment-client/src/Agent.cpp | 3 +- assignment-client/src/assets/AssetServer.cpp | 2 +- assignment-client/src/audio/AudioMixer.cpp | 2 +- assignment-client/src/avatars/AvatarMixer.cpp | 4 +- .../src/messages/MessagesMixer.cpp | 5 +- assignment-client/src/octree/OctreeServer.cpp | 4 +- .../src/scripts/EntityScriptServer.cpp | 161 +++++++++++++++++- .../src/scripts/EntityScriptServer.h | 17 +- domain-server/src/DomainServer.cpp | 4 +- 9 files changed, 186 insertions(+), 16 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index d13b708837..234ae239cd 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -54,7 +54,6 @@ static const int RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES = 10; Agent::Agent(ReceivedMessage& message) : ThreadedAssignment(message), - _entityEditSender(), _receivedAudioStream(RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES, RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES) { DependencyManager::get()->setPacketSender(&_entityEditSender); @@ -144,7 +143,7 @@ void Agent::handleAudioPacket(QSharedPointer message) { _receivedAudioStream.clearBuffer(); } -const QString AGENT_LOGGING_NAME = "agent"; +static const QString AGENT_LOGGING_NAME = "agent"; void Agent::run() { diff --git a/assignment-client/src/assets/AssetServer.cpp b/assignment-client/src/assets/AssetServer.cpp index 2fbe2f6dfe..017ffd94f1 100644 --- a/assignment-client/src/assets/AssetServer.cpp +++ b/assignment-client/src/assets/AssetServer.cpp @@ -137,7 +137,7 @@ void AssetServer::completeSetup() { cleanupUnmappedFiles(); } - nodeList->addNodeTypeToInterestSet(NodeType::Agent); + nodeList->addSetOfNodeTypesToNodeInterestSet({ NodeType::Agent, NodeType::EntityScriptServer }); } else { qCritical() << "Asset Server assignment will not continue because mapping file could not be loaded."; setFinished(true); diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 07639867eb..d5eb12c36d 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -398,7 +398,7 @@ void AudioMixer::start() { auto nodeList = DependencyManager::get(); // prepare the NodeList - nodeList->addNodeTypeToInterestSet(NodeType::Agent); + nodeList->addSetOfNodeTypesToNodeInterestSet({ NodeType::Agent, NodeType::EntityScriptServer }); nodeList->linkedDataCreateCallback = [&](Node* node) { getOrCreateClientData(node); }; // parse out any AudioMixer settings diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 11cbd73970..4568e1cedd 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -674,8 +674,8 @@ void AvatarMixer::run() { void AvatarMixer::domainSettingsRequestComplete() { auto nodeList = DependencyManager::get(); - nodeList->addNodeTypeToInterestSet(NodeType::Agent); - + nodeList->addSetOfNodeTypesToNodeInterestSet({ NodeType::Agent, NodeType::EntityScriptServer }); + // parse the settings to pull out the values we need parseDomainServerSettings(nodeList->getDomainHandler().getSettingsObject()); diff --git a/assignment-client/src/messages/MessagesMixer.cpp b/assignment-client/src/messages/MessagesMixer.cpp index 3baea67486..9555d1e160 100644 --- a/assignment-client/src/messages/MessagesMixer.cpp +++ b/assignment-client/src/messages/MessagesMixer.cpp @@ -83,5 +83,6 @@ void MessagesMixer::sendStatsPacket() { void MessagesMixer::run() { ThreadedAssignment::commonInit(MESSAGES_MIXER_LOGGING_NAME, NodeType::MessagesMixer); - DependencyManager::get()->addNodeTypeToInterestSet(NodeType::Agent); -} \ No newline at end of file + auto nodeList = DependencyManager::get(); + nodeList->addSetOfNodeTypesToNodeInterestSet({ NodeType::Agent, NodeType::EntityScriptServer }); +} diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 3e36250a82..7b681568b3 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -1136,8 +1136,8 @@ void OctreeServer::domainSettingsRequestComplete() { auto nodeList = DependencyManager::get(); // we need to ask the DS about agents so we can ping/reply with them - nodeList->addNodeTypeToInterestSet(NodeType::Agent); - + nodeList->addSetOfNodeTypesToNodeInterestSet({ NodeType::Agent, NodeType::EntityScriptServer }); + auto& packetReceiver = DependencyManager::get()->getPacketReceiver(); packetReceiver.registerListener(getMyQueryMessageType(), this, "handleOctreeQueryPacket"); packetReceiver.registerListener(PacketType::OctreeDataNack, this, "handleOctreeDataNackPacket"); diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index 66d1aa579d..2883d1a2ed 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -11,7 +11,166 @@ #include "EntityScriptServer.h" -EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : ThreadedAssignment(message) { +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../entities/AssignmentParentFinder.h" + +static const int RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES = 10; + +EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : + ThreadedAssignment(message), + _receivedAudioStream(RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES, RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES) +{ + DependencyManager::get()->setPacketSender(&_entityEditSender); + + ResourceManager::init(); + + DependencyManager::registerInheritance(); + + DependencyManager::set(); + DependencyManager::set(); + DependencyManager::set(); + + DependencyManager::set(); + DependencyManager::set(); + + + auto& packetReceiver = DependencyManager::get()->getPacketReceiver(); + + packetReceiver.registerListenerForTypes({ PacketType::MixedAudio, PacketType::SilentAudioFrame }, + this, "handleAudioPacket"); + packetReceiver.registerListenerForTypes({ PacketType::OctreeStats, PacketType::EntityData, PacketType::EntityErase }, + this, "handleOctreePacket"); + packetReceiver.registerListener(PacketType::Jurisdiction, this, "handleJurisdictionPacket"); + packetReceiver.registerListener(PacketType::SelectedAudioFormat, this, "handleSelectedAudioFormat"); } + +static const QString ENTITY_SCRIPT_SERVER_LOGGING_NAME = "entity-script-server"; + +void EntityScriptServer::run() { + // make sure we request our script once the agent connects to the domain + auto nodeList = DependencyManager::get(); + + ThreadedAssignment::commonInit(ENTITY_SCRIPT_SERVER_LOGGING_NAME, NodeType::EntityScriptServer); + + // Setup MessagesClient + auto messagesClient = DependencyManager::set(); + QThread* messagesThread = new QThread; + messagesThread->setObjectName("Messages Client Thread"); + messagesClient->moveToThread(messagesThread); + connect(messagesThread, &QThread::started, messagesClient.data(), &MessagesClient::init); + messagesThread->start(); + + // make sure we hear about connected nodes so we can grab an ATP script if a request is pending + connect(nodeList.data(), &LimitedNodeList::nodeActivated, this, &EntityScriptServer::nodeActivated); + connect(nodeList.data(), &LimitedNodeList::nodeKilled, this, &EntityScriptServer::nodeKilled); + + nodeList->addSetOfNodeTypesToNodeInterestSet({ + NodeType::AudioMixer, NodeType::AvatarMixer, NodeType::EntityServer, NodeType::MessagesMixer, NodeType::AssetServer + }); +} + +void EntityScriptServer::nodeActivated(SharedNodePointer activatedNode) { + if (activatedNode->getType() == NodeType::AudioMixer) { + negotiateAudioFormat(); + } +} + +void EntityScriptServer::negotiateAudioFormat() { + auto nodeList = DependencyManager::get(); + auto negotiateFormatPacket = NLPacket::create(PacketType::NegotiateAudioFormat); + auto codecPlugins = PluginManager::getInstance()->getCodecPlugins(); + quint8 numberOfCodecs = (quint8)codecPlugins.size(); + negotiateFormatPacket->writePrimitive(numberOfCodecs); + for (auto& plugin : codecPlugins) { + auto codecName = plugin->getName(); + negotiateFormatPacket->writeString(codecName); + } + + // grab our audio mixer from the NodeList, if it exists + SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer); + + if (audioMixer) { + // send off this mute packet + nodeList->sendPacket(std::move(negotiateFormatPacket), *audioMixer); + } +} + +void EntityScriptServer::handleSelectedAudioFormat(QSharedPointer message) { + QString selectedCodecName = message->readString(); + selectAudioFormat(selectedCodecName); +} + +void EntityScriptServer::selectAudioFormat(const QString& selectedCodecName) { + _selectedCodecName = selectedCodecName; + + qDebug() << "Selected Codec:" << _selectedCodecName; + + // release any old codec encoder/decoder first... + if (_codec && _encoder) { + _codec->releaseEncoder(_encoder); + _encoder = nullptr; + _codec = nullptr; + } + _receivedAudioStream.cleanupCodec(); + + auto codecPlugins = PluginManager::getInstance()->getCodecPlugins(); + for (auto& plugin : codecPlugins) { + if (_selectedCodecName == plugin->getName()) { + _codec = plugin; + _receivedAudioStream.setupCodec(plugin, _selectedCodecName, AudioConstants::STEREO); + _encoder = plugin->createEncoder(AudioConstants::SAMPLE_RATE, AudioConstants::MONO); + qDebug() << "Selected Codec Plugin:" << _codec.get(); + break; + } + } +} + +void EntityScriptServer::handleAudioPacket(QSharedPointer message) { + _receivedAudioStream.parseData(*message); + + _lastReceivedAudioLoudness = _receivedAudioStream.getNextOutputFrameLoudness(); + _receivedAudioStream.clearBuffer(); +} + +void EntityScriptServer::nodeKilled(SharedNodePointer killedNode) { + +} + +void EntityScriptServer::sendStatsPacket() { + +} + +void EntityScriptServer::handleOctreePacket(QSharedPointer message, SharedNodePointer senderNode) { + +} + +void EntityScriptServer::handleJurisdictionPacket(QSharedPointer message, SharedNodePointer senderNode) { + +} + +void EntityScriptServer::aboutToFinish() { + // our entity tree is going to go away so tell that to the EntityScriptingInterface + DependencyManager::get()->setEntityTree(nullptr); + + ResourceManager::cleanup(); + + // cleanup the AudioInjectorManager (and any still running injectors) + DependencyManager::destroy(); + DependencyManager::destroy(); + + // cleanup codec & encoder + if (_codec && _encoder) { + _codec->releaseEncoder(_encoder); + _encoder = nullptr; + } +} diff --git a/assignment-client/src/scripts/EntityScriptServer.h b/assignment-client/src/scripts/EntityScriptServer.h index 842f3802cf..2d69b46057 100644 --- a/assignment-client/src/scripts/EntityScriptServer.h +++ b/assignment-client/src/scripts/EntityScriptServer.h @@ -14,8 +14,11 @@ #include +#include +#include #include +#include "MixedAudioStream.h" class EntityScriptServer : public ThreadedAssignment { Q_OBJECT @@ -23,6 +26,8 @@ class EntityScriptServer : public ThreadedAssignment { public: EntityScriptServer(ReceivedMessage& message); + virtual void aboutToFinish() override; + public slots: void run() override; void nodeActivated(SharedNodePointer activatedNode); @@ -30,14 +35,22 @@ public slots: void sendStatsPacket() override; private slots: - void handleAudioPacket(QSharedPointer message); void handleOctreePacket(QSharedPointer message, SharedNodePointer senderNode); void handleJurisdictionPacket(QSharedPointer message, SharedNodePointer senderNode); void handleSelectedAudioFormat(QSharedPointer message); - + void handleAudioPacket(QSharedPointer message); + private: + void negotiateAudioFormat(); + void selectAudioFormat(const QString& selectedCodecName); + EntityEditPacketSender _entityEditSender; + QString _selectedCodecName; + CodecPluginPointer _codec; + Encoder* _encoder { nullptr }; + MixedAudioStream _receivedAudioStream; + float _lastReceivedAudioLoudness; }; #endif // hifi_EntityScriptServer_h diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 0f7923519b..791b337764 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -808,9 +808,7 @@ void DomainServer::populateDefaultStaticAssignmentsExcludingTypes(const QSet(static_cast(defaultedType) + 1)) { - if (!excludedTypes.contains(defaultedType) - && defaultedType != Assignment::UNUSED_1 - && defaultedType != Assignment::AgentType) { + if (!excludedTypes.contains(defaultedType) && defaultedType != Assignment::AgentType) { if (defaultedType == Assignment::AssetServerType) { // Make sure the asset-server is enabled before adding it here. From 5db37fff955eb45b978a3d852b82c70e67244288 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 17 Jan 2017 13:46:13 -0800 Subject: [PATCH 003/114] More entity script server work --- .../src/scripts/EntityScriptServer.cpp | 159 ++++++++++++++++-- .../src/scripts/EntityScriptServer.h | 20 ++- .../src/EntityTreeRenderer.cpp | 80 ++++----- .../physics/src/PhysicalEntitySimulation.h | 2 +- libraries/script-engine/src/ScriptEngines.h | 1 - 5 files changed, 190 insertions(+), 72 deletions(-) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index 2883d1a2ed..58e1d1e71b 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -11,6 +11,7 @@ #include "EntityScriptServer.h" +#include #include #include #include @@ -20,15 +21,13 @@ #include #include #include +#include #include "../entities/AssignmentParentFinder.h" -static const int RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES = 10; +int EntityScriptServer::_entitiesScriptEngineCount = 0; -EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : - ThreadedAssignment(message), - _receivedAudioStream(RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES, RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES) -{ +EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : ThreadedAssignment(message) { DependencyManager::get()->setPacketSender(&_entityEditSender); ResourceManager::init(); @@ -44,14 +43,15 @@ EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : auto& packetReceiver = DependencyManager::get()->getPacketReceiver(); - - packetReceiver.registerListenerForTypes({ PacketType::MixedAudio, PacketType::SilentAudioFrame }, - this, "handleAudioPacket"); packetReceiver.registerListenerForTypes({ PacketType::OctreeStats, PacketType::EntityData, PacketType::EntityErase }, this, "handleOctreePacket"); packetReceiver.registerListener(PacketType::Jurisdiction, this, "handleJurisdictionPacket"); packetReceiver.registerListener(PacketType::SelectedAudioFormat, this, "handleSelectedAudioFormat"); + auto avatarHashMap = DependencyManager::set(); + packetReceiver.registerListener(PacketType::BulkAvatarData, avatarHashMap.data(), "processAvatarDataPacket"); + packetReceiver.registerListener(PacketType::KillAvatar, avatarHashMap.data(), "processKillAvatar"); + packetReceiver.registerListener(PacketType::AvatarIdentity, avatarHashMap.data(), "processAvatarIdentityPacket"); } static const QString ENTITY_SCRIPT_SERVER_LOGGING_NAME = "entity-script-server"; @@ -77,6 +77,27 @@ void EntityScriptServer::run() { nodeList->addSetOfNodeTypesToNodeInterestSet({ NodeType::AudioMixer, NodeType::AvatarMixer, NodeType::EntityServer, NodeType::MessagesMixer, NodeType::AssetServer }); + + // Setup Script Engine + resetEntitiesScriptEngine(); + + // we need to make sure that init has been called for our EntityScriptingInterface + // so that it actually has a jurisdiction listener when we ask it for it next + auto entityScriptingInterface = DependencyManager::get(); + entityScriptingInterface->init(); + _entityViewer.setJurisdictionListener(entityScriptingInterface->getJurisdictionListener()); + + _entityViewer.init(); + + entityScriptingInterface->setEntityTree(_entityViewer.getTree()); + + DependencyManager::set(_entityViewer.getTree()); + + + auto tree = _entityViewer.getTree().get(); + connect(tree, &EntityTree::deletingEntity, this, &EntityScriptServer::deletingEntity, Qt::QueuedConnection); + connect(tree, &EntityTree::addingEntity, this, &EntityScriptServer::addingEntity, Qt::QueuedConnection); + connect(tree, &EntityTree::entityScriptChanging, this, &EntityScriptServer::entitySciptChanging, Qt::QueuedConnection); } void EntityScriptServer::nodeActivated(SharedNodePointer activatedNode) { @@ -121,13 +142,11 @@ void EntityScriptServer::selectAudioFormat(const QString& selectedCodecName) { _encoder = nullptr; _codec = nullptr; } - _receivedAudioStream.cleanupCodec(); auto codecPlugins = PluginManager::getInstance()->getCodecPlugins(); for (auto& plugin : codecPlugins) { if (_selectedCodecName == plugin->getName()) { _codec = plugin; - _receivedAudioStream.setupCodec(plugin, _selectedCodecName, AudioConstants::STEREO); _encoder = plugin->createEncoder(AudioConstants::SAMPLE_RATE, AudioConstants::MONO); qDebug() << "Selected Codec Plugin:" << _codec.get(); break; @@ -135,11 +154,91 @@ void EntityScriptServer::selectAudioFormat(const QString& selectedCodecName) { } } -void EntityScriptServer::handleAudioPacket(QSharedPointer message) { - _receivedAudioStream.parseData(*message); +void EntityScriptServer::resetEntitiesScriptEngine() { + auto engineName = QString("Entities %1").arg(++_entitiesScriptEngineCount); + auto newEngine = QSharedPointer(new ScriptEngine(NO_SCRIPT, engineName)); - _lastReceivedAudioLoudness = _receivedAudioStream.getNextOutputFrameLoudness(); - _receivedAudioStream.clearBuffer(); + newEngine->registerGlobalObject("EntityViewer", &_entityViewer); + + auto webSocketServerConstructorValue = newEngine->newFunction(WebSocketServerClass::constructor); + newEngine->globalObject().setProperty("WebSocketServer", webSocketServerConstructorValue); + + +// newEngine->setEmitScriptUpdatesFunction([this]() { +// SharedNodePointer entityServerNode = DependencyManager::get()->soloNodeOfType(NodeType::EntityServer); +// return !entityServerNode || isPhysicsEnabled(); +// }); + + newEngine->registerGlobalObject("AvatarList", DependencyManager::get().data()); + newEngine->registerGlobalObject("SoundCache", DependencyManager::get().data()); + + // connect this script engines printedMessage signal to the global ScriptEngines these various messages + auto scriptEngines = DependencyManager::get().data(); + connect(newEngine.data(), &ScriptEngine::printedMessage, scriptEngines, &ScriptEngines::onPrintedMessage); + connect(newEngine.data(), &ScriptEngine::errorMessage, scriptEngines, &ScriptEngines::onErrorMessage); + connect(newEngine.data(), &ScriptEngine::warningMessage, scriptEngines, &ScriptEngines::onWarningMessage); + connect(newEngine.data(), &ScriptEngine::infoMessage, scriptEngines, &ScriptEngines::onInfoMessage); + + + newEngine->runInThread(); + DependencyManager::get()->setEntitiesScriptEngine(newEngine.data()); + + _entitiesScriptEngine.swap(newEngine); +} + + +void EntityScriptServer::clear() { + // unload and stop the engine + if (_entitiesScriptEngine) { + // do this here (instead of in deleter) to avoid marshalling unload signals back to this thread + _entitiesScriptEngine->unloadAllEntityScripts(); + _entitiesScriptEngine->stop(); + } + + // reset the engine + if (!_shuttingDown) { + resetEntitiesScriptEngine(); + } + + _entityViewer.clear(); +} + +void EntityScriptServer::shutdown() { + if (_entitiesScriptEngine) { + _entitiesScriptEngine->disconnectNonEssentialSignals(); // disconnect all slots/signals from the script engine, except essential + } + _shuttingDown = true; + + clear(); // always clear() on shutdown +} + +void EntityScriptServer::addingEntity(const EntityItemID& entityID) { + checkAndCallPreload(entityID); +} + +void EntityScriptServer::deletingEntity(const EntityItemID& entityID) { + if (_entityViewer.getTree() && !_shuttingDown && _entitiesScriptEngine) { + _entitiesScriptEngine->unloadEntityScript(entityID); + } +} + +void EntityScriptServer::entitySciptChanging(const EntityItemID& entityID, const bool reload) { + if (_entityViewer.getTree() && !_shuttingDown) { + _entitiesScriptEngine->unloadEntityScript(entityID); + checkAndCallPreload(entityID, reload); + } +} + +void EntityScriptServer::checkAndCallPreload(const EntityItemID& entityID, const bool reload) { + if (_entityViewer.getTree() && !_shuttingDown) { + EntityItemPointer entity = _entityViewer.getTree()->findEntityByEntityItemID(entityID); + if (entity && entity->shouldPreloadScript() && _entitiesScriptEngine) { + QString scriptUrl = entity->getScript(); + scriptUrl = ResourceManager::normalizeURL(scriptUrl); + ScriptEngine::loadEntityScript(_entitiesScriptEngine, entityID, scriptUrl, reload); + entity->scriptHasPreloaded(); + } + } } void EntityScriptServer::nodeKilled(SharedNodePointer killedNode) { @@ -151,11 +250,43 @@ void EntityScriptServer::sendStatsPacket() { } void EntityScriptServer::handleOctreePacket(QSharedPointer message, SharedNodePointer senderNode) { + auto packetType = message->getType(); + if (packetType == PacketType::OctreeStats) { + + int statsMessageLength = OctreeHeadlessViewer::parseOctreeStats(message, senderNode); + if (message->getSize() > statsMessageLength) { + // pull out the piggybacked packet and create a new QSharedPointer for it + int piggyBackedSizeWithHeader = message->getSize() - statsMessageLength; + + auto buffer = std::unique_ptr(new char[piggyBackedSizeWithHeader]); + memcpy(buffer.get(), message->getRawMessage() + statsMessageLength, piggyBackedSizeWithHeader); + + auto newPacket = NLPacket::fromReceivedPacket(std::move(buffer), piggyBackedSizeWithHeader, message->getSenderSockAddr()); + message = QSharedPointer::create(*newPacket); + } else { + return; // bail since no piggyback data + } + + packetType = message->getType(); + } // fall through to piggyback message + + if (packetType == PacketType::EntityData) { + _entityViewer.processDatagram(*message, senderNode); + } else if (packetType == PacketType::EntityErase) { + _entityViewer.processEraseMessage(*message, senderNode); + } } void EntityScriptServer::handleJurisdictionPacket(QSharedPointer message, SharedNodePointer senderNode) { + NodeType_t nodeType; + message->peekPrimitive(&nodeType); + // PacketType_JURISDICTION, first byte is the node type... + if (nodeType == NodeType::EntityServer) { + DependencyManager::get()->getJurisdictionListener()-> + queueReceivedPacket(message, senderNode); + } } void EntityScriptServer::aboutToFinish() { diff --git a/assignment-client/src/scripts/EntityScriptServer.h b/assignment-client/src/scripts/EntityScriptServer.h index 2d69b46057..63b1418534 100644 --- a/assignment-client/src/scripts/EntityScriptServer.h +++ b/assignment-client/src/scripts/EntityScriptServer.h @@ -15,11 +15,11 @@ #include #include +#include #include +#include #include -#include "MixedAudioStream.h" - class EntityScriptServer : public ThreadedAssignment { Q_OBJECT @@ -38,19 +38,29 @@ private slots: void handleOctreePacket(QSharedPointer message, SharedNodePointer senderNode); void handleJurisdictionPacket(QSharedPointer message, SharedNodePointer senderNode); void handleSelectedAudioFormat(QSharedPointer message); - void handleAudioPacket(QSharedPointer message); private: void negotiateAudioFormat(); void selectAudioFormat(const QString& selectedCodecName); + void resetEntitiesScriptEngine(); + void clear(); + void shutdown(); + void addingEntity(const EntityItemID& entityID); + void deletingEntity(const EntityItemID& entityID); + void entitySciptChanging(const EntityItemID& entityID, const bool reload); + void checkAndCallPreload(const EntityItemID& entityID, const bool reload = false); + + bool _shuttingDown { false }; + + static int _entitiesScriptEngineCount; + QSharedPointer _entitiesScriptEngine; EntityEditPacketSender _entityEditSender; + EntityTreeHeadlessViewer _entityViewer; QString _selectedCodecName; CodecPluginPointer _codec; Encoder* _encoder { nullptr }; - MixedAudioStream _receivedAudioStream; - float _lastReceivedAudioLoudness; }; #endif // hifi_EntityScriptServer_h diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 7b80e97767..f851bdfe24 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -45,9 +45,7 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterface* viewState, AbstractScriptingServicesInterface* scriptingServices) : - OctreeRenderer(), _wantScripts(wantScripts), - _entitiesScriptEngine(NULL), _lastPointerEventValid(false), _viewState(viewState), _scriptingServices(scriptingServices), @@ -106,6 +104,35 @@ void EntityTreeRenderer::resetEntitiesScriptEngine() { auto newEngine = new ScriptEngine(NO_SCRIPT, QString("Entities %1").arg(++_entitiesScriptEngineCount)); _entitiesScriptEngine = QSharedPointer(newEngine, entitiesScriptEngineDeleter); + auto makeSlotForSignal = [&](QString name) { + return [newEngine, name](const EntityItemID& entityItemID, const PointerEvent& event) { + newEngine->callEntityScriptMethod(entityItemID, name, event); + }; + }; + + auto makeSlotForSignalNoEvent = [&](QString name) { + return [newEngine, name](const EntityItemID& entityItemID) { + newEngine->callEntityScriptMethod(entityItemID, name); + }; + }; + + connect(this, &EntityTreeRenderer::mousePressOnEntity, newEngine, makeSlotForSignal("mousePressOnEntity")); + connect(this, &EntityTreeRenderer::mouseMoveOnEntity, newEngine, makeSlotForSignal("mouseMoveOnEntity")); + connect(this, &EntityTreeRenderer::mouseMoveOnEntity, newEngine, makeSlotForSignal("mouseMoveEvent")); + connect(this, &EntityTreeRenderer::mouseReleaseOnEntity, newEngine, makeSlotForSignal("mouseReleaseOnEntity")); + + connect(this, &EntityTreeRenderer::clickDownOnEntity, newEngine, makeSlotForSignal("clickDownOnEntity")); + connect(this, &EntityTreeRenderer::holdingClickOnEntity, newEngine, makeSlotForSignal("holdingClickOnEntity")); + connect(this, &EntityTreeRenderer::clickReleaseOnEntity, newEngine, makeSlotForSignal("clickReleaseOnEntity")); + + connect(this, &EntityTreeRenderer::hoverEnterEntity, newEngine, makeSlotForSignal("hoverEnterEntity")); + connect(this, &EntityTreeRenderer::hoverOverEntity, newEngine, makeSlotForSignal("hoverOverEntity")); + connect(this, &EntityTreeRenderer::hoverLeaveEntity, newEngine, makeSlotForSignal("hoverLeaveEntity")); + + connect(this, &EntityTreeRenderer::enterEntity, newEngine, makeSlotForSignalNoEvent("enterEntity")); + connect(this, &EntityTreeRenderer::leaveEntity, newEngine, makeSlotForSignalNoEvent("leaveEntity")); + + _scriptingServices->registerScriptEngineWithApplicationServices(_entitiesScriptEngine.data()); _entitiesScriptEngine->runInThread(); DependencyManager::get()->setEntitiesScriptEngine(_entitiesScriptEngine.data()); @@ -208,7 +235,6 @@ void EntityTreeRenderer::update() { // and we want to simulate this message here as well as in mouse move if (_lastPointerEventValid && !_currentClickingOnEntityID.isInvalidID()) { emit holdingClickOnEntity(_currentClickingOnEntityID, _lastPointerEvent); - _entitiesScriptEngine->callEntityScriptMethod(_currentClickingOnEntityID, "holdingClickOnEntity", _lastPointerEvent); } } @@ -302,9 +328,6 @@ bool EntityTreeRenderer::checkEnterLeaveEntities() { foreach(const EntityItemID& entityID, _currentEntitiesInside) { if (!entitiesContainingAvatar.contains(entityID)) { emit leaveEntity(entityID); - if (_entitiesScriptEngine) { - _entitiesScriptEngine->callEntityScriptMethod(entityID, "leaveEntity"); - } } } @@ -312,9 +335,6 @@ bool EntityTreeRenderer::checkEnterLeaveEntities() { foreach(const EntityItemID& entityID, entitiesContainingAvatar) { if (!_currentEntitiesInside.contains(entityID)) { emit enterEntity(entityID); - if (_entitiesScriptEngine) { - _entitiesScriptEngine->callEntityScriptMethod(entityID, "enterEntity"); - } } } _currentEntitiesInside = entitiesContainingAvatar; @@ -329,9 +349,6 @@ void EntityTreeRenderer::leaveAllEntities() { // for all of our previous containing entities, if they are no longer containing then send them a leave event foreach(const EntityItemID& entityID, _currentEntitiesInside) { emit leaveEntity(entityID); - if (_entitiesScriptEngine) { - _entitiesScriptEngine->callEntityScriptMethod(entityID, "leaveEntity"); - } } _currentEntitiesInside.clear(); forceRecheckEntities(); @@ -719,15 +736,8 @@ void EntityTreeRenderer::mousePressEvent(QMouseEvent* event) { emit mousePressOnEntity(rayPickResult.entityID, pointerEvent); - if (_entitiesScriptEngine) { - _entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "mousePressOnEntity", pointerEvent); - } - _currentClickingOnEntityID = rayPickResult.entityID; emit clickDownOnEntity(_currentClickingOnEntityID, pointerEvent); - if (_entitiesScriptEngine) { - _entitiesScriptEngine->callEntityScriptMethod(_currentClickingOnEntityID, "clickDownOnEntity", pointerEvent); - } _lastPointerEvent = pointerEvent; _lastPointerEventValid = true; @@ -758,9 +768,6 @@ void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event) { toPointerButton(*event), toPointerButtons(*event)); emit mouseReleaseOnEntity(rayPickResult.entityID, pointerEvent); - if (_entitiesScriptEngine) { - _entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "mouseReleaseOnEntity", pointerEvent); - } _lastPointerEvent = pointerEvent; _lastPointerEventValid = true; @@ -778,9 +785,6 @@ void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event) { toPointerButton(*event), toPointerButtons(*event)); emit clickReleaseOnEntity(_currentClickingOnEntityID, pointerEvent); - if (_entitiesScriptEngine) { - _entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "clickReleaseOnEntity", pointerEvent); - } } // makes it the unknown ID, we just released so we can't be clicking on anything @@ -809,11 +813,6 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) { emit mouseMoveOnEntity(rayPickResult.entityID, pointerEvent); - if (_entitiesScriptEngine) { - _entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "mouseMoveEvent", pointerEvent); - _entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "mouseMoveOnEntity", pointerEvent); - } - // handle the hover logic... // if we were previously hovering over an entity, and this new entity is not the same as our previous entity @@ -828,26 +827,17 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) { toPointerButton(*event), toPointerButtons(*event)); emit hoverLeaveEntity(_currentHoverOverEntityID, pointerEvent); - if (_entitiesScriptEngine) { - _entitiesScriptEngine->callEntityScriptMethod(_currentHoverOverEntityID, "hoverLeaveEntity", pointerEvent); - } } // If the new hover entity does not match the previous hover entity then we are entering the new one // this is true if the _currentHoverOverEntityID is known or unknown if (rayPickResult.entityID != _currentHoverOverEntityID) { emit hoverEnterEntity(rayPickResult.entityID, pointerEvent); - if (_entitiesScriptEngine) { - _entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "hoverEnterEntity", pointerEvent); - } } // and finally, no matter what, if we're intersecting an entity then we're definitely hovering over it, and // we should send our hover over event emit hoverOverEntity(rayPickResult.entityID, pointerEvent); - if (_entitiesScriptEngine) { - _entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "hoverOverEntity", pointerEvent); - } // remember what we're hovering over _currentHoverOverEntityID = rayPickResult.entityID; @@ -869,9 +859,6 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) { toPointerButton(*event), toPointerButtons(*event)); emit hoverLeaveEntity(_currentHoverOverEntityID, pointerEvent); - if (_entitiesScriptEngine) { - _entitiesScriptEngine->callEntityScriptMethod(_currentHoverOverEntityID, "hoverLeaveEntity", pointerEvent); - } _currentHoverOverEntityID = UNKNOWN_ENTITY_ID; // makes it the unknown ID } } @@ -888,9 +875,6 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) { toPointerButton(*event), toPointerButtons(*event)); emit holdingClickOnEntity(_currentClickingOnEntityID, pointerEvent); - if (_entitiesScriptEngine) { - _entitiesScriptEngine->callEntityScriptMethod(_currentClickingOnEntityID, "holdingClickOnEntity", pointerEvent); - } } } @@ -1058,16 +1042,10 @@ void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, cons // And now the entity scripts if (isCollisionOwner(myNodeID, entityTree, idA, collision)) { emit collisionWithEntity(idA, idB, collision); - if (_entitiesScriptEngine) { - _entitiesScriptEngine->callEntityScriptMethod(idA, "collisionWithEntity", idB, collision); - } } if (isCollisionOwner(myNodeID, entityTree, idA, collision)) { emit collisionWithEntity(idB, idA, collision); - if (_entitiesScriptEngine) { - _entitiesScriptEngine->callEntityScriptMethod(idB, "collisionWithEntity", idA, collision); - } } } diff --git a/libraries/physics/src/PhysicalEntitySimulation.h b/libraries/physics/src/PhysicalEntitySimulation.h index 24b9ba95f0..af5def9775 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.h +++ b/libraries/physics/src/PhysicalEntitySimulation.h @@ -27,7 +27,7 @@ class PhysicalEntitySimulation; using PhysicalEntitySimulationPointer = std::shared_ptr; using SetOfEntityMotionStates = QSet; -class PhysicalEntitySimulation :public EntitySimulation { +class PhysicalEntitySimulation : public EntitySimulation { public: PhysicalEntitySimulation(); ~PhysicalEntitySimulation(); diff --git a/libraries/script-engine/src/ScriptEngines.h b/libraries/script-engine/src/ScriptEngines.h index 583b6c0ea2..b0f0e24ac6 100644 --- a/libraries/script-engine/src/ScriptEngines.h +++ b/libraries/script-engine/src/ScriptEngines.h @@ -90,7 +90,6 @@ public slots: protected slots: void onScriptFinished(const QString& fileNameString, ScriptEngine* engine); - protected: friend class ScriptEngine; From 8d199ded1538ad8e36a386e62ab8dda47b1fd7f8 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 17 Jan 2017 13:46:56 -0800 Subject: [PATCH 004/114] Check collision against the right owner --- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index f851bdfe24..dbfbf23517 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -1044,7 +1044,7 @@ void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, cons emit collisionWithEntity(idA, idB, collision); } - if (isCollisionOwner(myNodeID, entityTree, idA, collision)) { + if (isCollisionOwner(myNodeID, entityTree, idB, collision)) { emit collisionWithEntity(idB, idA, collision); } } From 1212fefa612f2e9cb0cdf8c2da5d16c9918627de Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 17 Jan 2017 13:47:19 -0800 Subject: [PATCH 005/114] Check for avatar collision in assignment as well --- .../src/entities/AssignmentParentFinder.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/assignment-client/src/entities/AssignmentParentFinder.cpp b/assignment-client/src/entities/AssignmentParentFinder.cpp index a0232daff4..ff167de9cf 100644 --- a/assignment-client/src/entities/AssignmentParentFinder.cpp +++ b/assignment-client/src/entities/AssignmentParentFinder.cpp @@ -11,6 +11,8 @@ #include "AssignmentParentFinder.h" +#include + SpatiallyNestableWeakPointer AssignmentParentFinder::find(QUuid parentID, bool& success, SpatialParentTree* entityTree) const { SpatiallyNestableWeakPointer parent; @@ -25,10 +27,19 @@ SpatiallyNestableWeakPointer AssignmentParentFinder::find(QUuid parentID, bool& } else { parent = _tree->findEntityByEntityItemID(parentID); } - if (parent.expired()) { - success = false; - } else { + if (!parent.expired()) { success = true; + return parent; } + + // search avatars + auto avatarHashMap = DependencyManager::get(); + parent = avatarHashMap->getAvatarBySessionID(parentID); + if (!parent.expired()) { + success = true; + return parent; + } + + success = false; return parent; } From b0c2a9d614e388f099afa361cdc88f9622f06618 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 12 Jan 2017 16:51:29 -0800 Subject: [PATCH 006/114] Add serverScripts entity property --- libraries/entities/src/EntityItem.cpp | 5 +++++ libraries/entities/src/EntityItem.h | 6 +++++- libraries/entities/src/EntityItemProperties.cpp | 10 ++++++++++ libraries/entities/src/EntityItemProperties.h | 2 ++ libraries/entities/src/EntityItemPropertiesDefaults.h | 1 + libraries/entities/src/EntityPropertyFlags.h | 2 ++ libraries/networking/src/udt/PacketHeaders.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 1 + 8 files changed, 27 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 00c9ab2dde..b640f7bd8d 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -121,6 +121,7 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param requestedProperties += PROP_LIFETIME; requestedProperties += PROP_SCRIPT; requestedProperties += PROP_SCRIPT_TIMESTAMP; + requestedProperties += PROP_SERVER_SCRIPTS; requestedProperties += PROP_COLLISION_SOUND_URL; requestedProperties += PROP_REGISTRATION_POINT; requestedProperties += PROP_ANGULAR_DAMPING; @@ -265,6 +266,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet APPEND_ENTITY_PROPERTY(PROP_LIFETIME, getLifetime()); APPEND_ENTITY_PROPERTY(PROP_SCRIPT, getScript()); APPEND_ENTITY_PROPERTY(PROP_SCRIPT_TIMESTAMP, getScriptTimestamp()); + APPEND_ENTITY_PROPERTY(PROP_SERVER_SCRIPTS, getServerScripts()); APPEND_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, getRegistrationPoint()); APPEND_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, getAngularDamping()); APPEND_ENTITY_PROPERTY(PROP_VISIBLE, getVisible()); @@ -778,6 +780,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY(PROP_LIFETIME, float, updateLifetime); READ_ENTITY_PROPERTY(PROP_SCRIPT, QString, setScript); READ_ENTITY_PROPERTY(PROP_SCRIPT_TIMESTAMP, quint64, setScriptTimestamp); + READ_ENTITY_PROPERTY(PROP_SERVER_SCRIPTS, QString, setServerScripts); READ_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, glm::vec3, updateRegistrationPoint); READ_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, float, updateAngularDamping); @@ -1186,6 +1189,7 @@ EntityItemProperties EntityItem::getProperties(EntityPropertyFlags desiredProper COPY_ENTITY_PROPERTY_TO_PROPERTIES(lifetime, getLifetime); COPY_ENTITY_PROPERTY_TO_PROPERTIES(script, getScript); COPY_ENTITY_PROPERTY_TO_PROPERTIES(scriptTimestamp, getScriptTimestamp); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(serverScripts, getServerScripts); COPY_ENTITY_PROPERTY_TO_PROPERTIES(collisionSoundURL, getCollisionSoundURL); COPY_ENTITY_PROPERTY_TO_PROPERTIES(registrationPoint, getRegistrationPoint); COPY_ENTITY_PROPERTY_TO_PROPERTIES(angularVelocity, getLocalAngularVelocity); @@ -1298,6 +1302,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) { // non-simulation properties below SET_ENTITY_PROPERTY_FROM_PROPERTIES(script, setScript); SET_ENTITY_PROPERTY_FROM_PROPERTIES(scriptTimestamp, setScriptTimestamp); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(serverScripts, setServerScripts); SET_ENTITY_PROPERTY_FROM_PROPERTIES(collisionSoundURL, setCollisionSoundURL); SET_ENTITY_PROPERTY_FROM_PROPERTIES(localRenderAlpha, setLocalRenderAlpha); SET_ENTITY_PROPERTY_FROM_PROPERTIES(visible, setVisible); diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index bd5fb44fc8..505d90bb81 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -254,12 +254,15 @@ public: using SpatiallyNestable::getQueryAACube; virtual AACube getQueryAACube(bool& success) const override; - const QString& getScript() const { return _script; } + const QString getScript() const { return _script; } void setScript(const QString& value) { _script = value; } quint64 getScriptTimestamp() const { return _scriptTimestamp; } void setScriptTimestamp(const quint64 value) { _scriptTimestamp = value; } + const QString getServerScripts() const { return _serverScripts; } + void setServerScripts(const QString& serverScripts) { _serverScripts = serverScripts; } + const QString& getCollisionSoundURL() const { return _collisionSoundURL; } void setCollisionSoundURL(const QString& value); @@ -510,6 +513,7 @@ protected: QString _script; /// the value of the script property QString _loadedScript; /// the value of _script when the last preload signal was sent quint64 _scriptTimestamp{ ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP }; /// the script loaded property used for forced reload + QString _serverScripts; /// the value of _scriptTimestamp when the last preload signal was sent // NOTE: on construction we want this to be different from _scriptTimestamp so we intentionally bump it diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 927708fc4b..adc0fba1be 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -241,6 +241,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_LIFETIME, lifetime); CHECK_PROPERTY_CHANGE(PROP_SCRIPT, script); CHECK_PROPERTY_CHANGE(PROP_SCRIPT_TIMESTAMP, scriptTimestamp); + CHECK_PROPERTY_CHANGE(PROP_SERVER_SCRIPTS, serverScripts); CHECK_PROPERTY_CHANGE(PROP_COLLISION_SOUND_URL, collisionSoundURL); CHECK_PROPERTY_CHANGE(PROP_COLOR, color); CHECK_PROPERTY_CHANGE(PROP_COLOR_SPREAD, colorSpread); @@ -388,6 +389,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LIFETIME, lifetime); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SCRIPT, script); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SCRIPT_TIMESTAMP, scriptTimestamp); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SERVER_SCRIPTS, serverScripts); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_REGISTRATION_POINT, registrationPoint); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ANGULAR_VELOCITY, angularVelocity); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ANGULAR_DAMPING, angularDamping); @@ -628,6 +630,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(lifetime, float, setLifetime); COPY_PROPERTY_FROM_QSCRIPTVALUE(script, QString, setScript); COPY_PROPERTY_FROM_QSCRIPTVALUE(scriptTimestamp, quint64, setScriptTimestamp); + COPY_PROPERTY_FROM_QSCRIPTVALUE(serverScripts, QString, setServerScripts); COPY_PROPERTY_FROM_QSCRIPTVALUE(registrationPoint, glmVec3, setRegistrationPoint); COPY_PROPERTY_FROM_QSCRIPTVALUE(angularVelocity, glmVec3, setAngularVelocity); COPY_PROPERTY_FROM_QSCRIPTVALUE(angularDamping, float, setAngularDamping); @@ -934,6 +937,7 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_PROPERTY_TO_MAP(PROP_LIFETIME, Lifetime, lifetime, float); ADD_PROPERTY_TO_MAP(PROP_SCRIPT, Script, script, QString); ADD_PROPERTY_TO_MAP(PROP_SCRIPT_TIMESTAMP, ScriptTimestamp, scriptTimestamp, quint64); + ADD_PROPERTY_TO_MAP(PROP_SERVER_SCRIPTS, ServerScripts, serverScripts, QString); ADD_PROPERTY_TO_MAP(PROP_COLLISION_SOUND_URL, CollisionSoundURL, collisionSoundURL, QString); ADD_PROPERTY_TO_MAP(PROP_COLOR, Color, color, xColor); ADD_PROPERTY_TO_MAP(PROP_COLOR_SPREAD, ColorSpread, colorSpread, xColor); @@ -1201,6 +1205,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem APPEND_ENTITY_PROPERTY(PROP_LIFETIME, properties.getLifetime()); APPEND_ENTITY_PROPERTY(PROP_SCRIPT, properties.getScript()); APPEND_ENTITY_PROPERTY(PROP_SCRIPT_TIMESTAMP, properties.getScriptTimestamp()); + APPEND_ENTITY_PROPERTY(PROP_SERVER_SCRIPTS, properties.getServerScripts()); APPEND_ENTITY_PROPERTY(PROP_COLOR, properties.getColor()); APPEND_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, properties.getRegistrationPoint()); APPEND_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, properties.getAngularVelocity()); @@ -1501,6 +1506,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LIFETIME, float, setLifetime); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SCRIPT, QString, setScript); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SCRIPT_TIMESTAMP, quint64, setScriptTimestamp); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SERVER_SCRIPTS, QString, setServerScripts); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR, xColor, setColor); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_REGISTRATION_POINT, glm::vec3, setRegistrationPoint); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANGULAR_VELOCITY, glm::vec3, setAngularVelocity); @@ -1688,6 +1694,7 @@ void EntityItemProperties::markAllChanged() { _userDataChanged = true; _scriptChanged = true; _scriptTimestampChanged = true; + _serverScriptsChanged = true; _collisionSoundURLChanged = true; _registrationPointChanged = true; _angularVelocityChanged = true; @@ -1896,6 +1903,9 @@ QList EntityItemProperties::listChangedProperties() { if (scriptTimestampChanged()) { out += "scriptTimestamp"; } + if (serverScriptsChanged()) { + out += "serverScripts"; + } if (collisionSoundURLChanged()) { out += "collisionSoundURL"; } diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index fb08182a2e..c1f6470490 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -221,6 +221,8 @@ public: DEFINE_PROPERTY_REF(PROP_LAST_EDITED_BY, LastEditedBy, lastEditedBy, QUuid, ENTITY_ITEM_DEFAULT_LAST_EDITED_BY); + DEFINE_PROPERTY_REF(PROP_SERVER_SCRIPTS, ServerScripts, serverScripts, QString, ""); + static QString getBackgroundModeString(BackgroundMode mode); diff --git a/libraries/entities/src/EntityItemPropertiesDefaults.h b/libraries/entities/src/EntityItemPropertiesDefaults.h index ca7ac669f3..d52c5d9aab 100644 --- a/libraries/entities/src/EntityItemPropertiesDefaults.h +++ b/libraries/entities/src/EntityItemPropertiesDefaults.h @@ -35,6 +35,7 @@ const bool ENTITY_ITEM_DEFAULT_VISIBLE = true; const QString ENTITY_ITEM_DEFAULT_SCRIPT = QString(""); const quint64 ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP = 0; +const QString ENTITY_ITEM_DEFAULT_SERVER_SCRIPTS = QString(""); const QString ENTITY_ITEM_DEFAULT_COLLISION_SOUND_URL = QString(""); const glm::vec3 ENTITY_ITEM_DEFAULT_REGISTRATION_POINT = ENTITY_ITEM_HALF_VEC3; // center diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 127f3d0eea..b77d3cc077 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -183,6 +183,8 @@ enum EntityPropertyList { PROP_LAST_EDITED_BY, + PROP_SERVER_SCRIPTS, + //////////////////////////////////////////////////////////////////////////////////////////////////// // ATTENTION: add new properties to end of list just ABOVE this line PROP_AFTER_LAST_ITEM, diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 46d6915a12..48a570d803 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -48,7 +48,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::EntityAdd: case PacketType::EntityEdit: case PacketType::EntityData: - return VERSION_ENTITIES_LAST_EDITED_BY; + return VERSION_ENTITIES_SERVER_SCRIPTS; case PacketType::AvatarIdentity: case PacketType::AvatarData: case PacketType::BulkAvatarData: diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index c012ed8f67..4c5ef53ee7 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -197,6 +197,7 @@ const PacketVersion VERSION_MODEL_ENTITIES_SUPPORT_SIMPLE_HULLS = 62; const PacketVersion VERSION_WEB_ENTITIES_SUPPORT_DPI = 63; const PacketVersion VERSION_ENTITIES_ARROW_ACTION = 64; const PacketVersion VERSION_ENTITIES_LAST_EDITED_BY = 65; +const PacketVersion VERSION_ENTITIES_SERVER_SCRIPTS = 66; enum class AssetServerPacketVersion: PacketVersion { VegasCongestionControl = 19 From 142c7da5232157fd1dcce440803edca0bb2a60ec Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 13 Jan 2017 09:18:50 -0800 Subject: [PATCH 007/114] Add serverScripts property support to edit.js --- scripts/system/html/entityProperties.html | 4 ++++ scripts/system/html/js/entityProperties.js | 3 +++ 2 files changed, 7 insertions(+) diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index 1de59ad135..265e9336d1 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -318,6 +318,10 @@ +
+ + +
M
diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 4fe13196f3..77d47691ea 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -591,6 +591,7 @@ function loaded() { var elScriptURL = document.getElementById("property-script-url"); var elScriptTimestamp = document.getElementById("property-script-timestamp"); var elReloadScriptButton = document.getElementById("reload-script-button"); + var elServerScripts = document.getElementById("property-server-scripts"); var elUserData = document.getElementById("property-user-data"); var elClearUserData = document.getElementById("userdata-clear"); var elSaveUserData = document.getElementById("userdata-save"); @@ -847,6 +848,7 @@ function loaded() { elLifetime.value = properties.lifetime; elScriptURL.value = properties.script; elScriptTimestamp.value = properties.scriptTimestamp; + elServerScripts.value = properties.serverScripts; var json = null; try { @@ -1143,6 +1145,7 @@ function loaded() { elLifetime.addEventListener('change', createEmitNumberPropertyUpdateFunction('lifetime')); elScriptURL.addEventListener('change', createEmitTextPropertyUpdateFunction('script')); elScriptTimestamp.addEventListener('change', createEmitNumberPropertyUpdateFunction('scriptTimestamp')); + elServerScripts.addEventListener('change', createEmitTextPropertyUpdateFunction('serverScripts')); elClearUserData.addEventListener("click", function() { deleteJSONEditor(); From 812aaee48c52cdeccea68ff31c7d1545fd92afb8 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 13 Jan 2017 12:06:34 -0800 Subject: [PATCH 008/114] Add Entities.reloadServerScripts --- .../entities/src/EntityScriptingInterface.cpp | 20 +++++++++++++++++++ .../entities/src/EntityScriptingInterface.h | 2 ++ libraries/networking/src/udt/PacketHeaders.h | 3 ++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 498e0959c6..f90fddfc5a 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -670,6 +670,26 @@ RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersectionWorke return result; } +bool EntityScriptingInterface::reloadServerScripts(QUuid entityID) { + // Send packet to entity script server + auto nodeList = DependencyManager::get(); + SharedNodePointer entityScriptServer = nodeList->soloNodeOfType(NodeType::AssetServer); + + if (entityScriptServer) { + auto id = entityID.toByteArray(); + auto payloadSize = id.size(); + auto packet = NLPacket::create(PacketType::ReloadEntityServerScript, payloadSize, true); + + packet->write(id); + + if (nodeList->sendPacket(std::move(packet), *entityScriptServer) != -1) { + return true; + } + } + + return false; +} + void EntityScriptingInterface::setLightsArePickable(bool value) { LightEntityItem::setLightsArePickable(value); } diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index a14b67c77c..30739782ea 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -210,6 +210,8 @@ public slots: /// order to return an accurate result Q_INVOKABLE RayToEntityIntersectionResult findRayIntersectionBlocking(const PickRay& ray, bool precisionPicking = false, const QScriptValue& entityIdsToInclude = QScriptValue(), const QScriptValue& entityIdsToDiscard = QScriptValue()); + Q_INVOKABLE bool reloadServerScripts(QUuid entityID); + Q_INVOKABLE void setLightsArePickable(bool value); Q_INVOKABLE bool getLightsArePickable() const; diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 4c5ef53ee7..346263b312 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -107,7 +107,8 @@ public: RequestsDomainListData, ExitingSpaceBubble, PerAvatarGainSet, - LAST_PACKET_TYPE = PerAvatarGainSet + ReloadEntityServerScript, + LAST_PACKET_TYPE = ReloadEntityServerScript }; }; From 71e039951c2e78423506ba85cdde3c301148c4a8 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 13 Jan 2017 12:07:12 -0800 Subject: [PATCH 009/114] Add reload server scripts button to edit.js --- scripts/system/edit.js | 8 +++++++- scripts/system/html/entityProperties.html | 3 ++- scripts/system/html/js/entityProperties.js | 14 +++++++++++--- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index afcfd50bb8..3e97c54c43 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -1569,7 +1569,7 @@ var PropertiesTool = function (opts) { pushCommandForSelections(); selectionManager._update(); } - } else if (data.action === "reloadScript") { + } else if (data.action === "reloadClientScripts") { if (selectionManager.hasSelection()) { var timestamp = Date.now(); for (i = 0; i < selectionManager.selections.length; i++) { @@ -1578,6 +1578,12 @@ var PropertiesTool = function (opts) { }); } } + } else if (data.action === "reloadServerScripts") { + if (selectionManager.hasSelection()) { + for (i = 0; i < selectionManager.selections.length; i++) { + Entities.reloadServerScripts(selectionManager.selections[i]); + } + } } } }); diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index 265e9336d1..07a1b300d1 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -318,9 +318,10 @@ -
+
+
M diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 77d47691ea..ebd1e67677 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -590,8 +590,9 @@ function loaded() { var elLifetime = document.getElementById("property-lifetime"); var elScriptURL = document.getElementById("property-script-url"); var elScriptTimestamp = document.getElementById("property-script-timestamp"); - var elReloadScriptButton = document.getElementById("reload-script-button"); + var elReloadScriptsButton = document.getElementById("reload-script-button"); var elServerScripts = document.getElementById("property-server-scripts"); + var elReloadServerScriptsButton = document.getElementById("reload-server-scripts-button"); var elUserData = document.getElementById("property-user-data"); var elClearUserData = document.getElementById("userdata-clear"); var elSaveUserData = document.getElementById("userdata-save"); @@ -1398,12 +1399,19 @@ function loaded() { percentage: parseInt(elRescaleDimensionsPct.value), })); }); - elReloadScriptButton.addEventListener("click", function() { + elReloadScriptsButton.addEventListener("click", function() { EventBridge.emitWebEvent(JSON.stringify({ type: "action", - action: "reloadScript" + action: "reloadClientScripts" })); }); + elReloadServerScriptsButton.addEventListener("click", function() { + EventBridge.emitWebEvent(JSON.stringify({ + type: "action", + action: "reloadServerScripts" + })); + }); + window.onblur = function() { // Fake a change event From 340eeb94fafd121a433890edfe848e1ec6928e21 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 17 Jan 2017 15:24:14 -0800 Subject: [PATCH 010/114] Add return type to lambdas in EntityTreeRenderer --- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index dbfbf23517..0f61be291f 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -104,13 +104,13 @@ void EntityTreeRenderer::resetEntitiesScriptEngine() { auto newEngine = new ScriptEngine(NO_SCRIPT, QString("Entities %1").arg(++_entitiesScriptEngineCount)); _entitiesScriptEngine = QSharedPointer(newEngine, entitiesScriptEngineDeleter); - auto makeSlotForSignal = [&](QString name) { + auto makeSlotForSignal = [&](QString name) -> std::function { return [newEngine, name](const EntityItemID& entityItemID, const PointerEvent& event) { newEngine->callEntityScriptMethod(entityItemID, name, event); }; }; - auto makeSlotForSignalNoEvent = [&](QString name) { + auto makeSlotForSignalNoEvent = [&](QString name) -> std::function { return [newEngine, name](const EntityItemID& entityItemID) { newEngine->callEntityScriptMethod(entityItemID, name); }; From ff3f175fb7809b9929b96a862d3e3568cd7ad6c2 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 17 Jan 2017 15:39:54 -0800 Subject: [PATCH 011/114] Fix typos --- assignment-client/src/scripts/EntityScriptServer.cpp | 4 ++-- assignment-client/src/scripts/EntityScriptServer.h | 2 +- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 4 ++-- libraries/entities-renderer/src/EntityTreeRenderer.h | 2 +- libraries/ui/src/Tooltip.cpp | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index 58e1d1e71b..010a827eb9 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -97,7 +97,7 @@ void EntityScriptServer::run() { auto tree = _entityViewer.getTree().get(); connect(tree, &EntityTree::deletingEntity, this, &EntityScriptServer::deletingEntity, Qt::QueuedConnection); connect(tree, &EntityTree::addingEntity, this, &EntityScriptServer::addingEntity, Qt::QueuedConnection); - connect(tree, &EntityTree::entityScriptChanging, this, &EntityScriptServer::entitySciptChanging, Qt::QueuedConnection); + connect(tree, &EntityTree::entityScriptChanging, this, &EntityScriptServer::entityScriptChanging, Qt::QueuedConnection); } void EntityScriptServer::nodeActivated(SharedNodePointer activatedNode) { @@ -222,7 +222,7 @@ void EntityScriptServer::deletingEntity(const EntityItemID& entityID) { } } -void EntityScriptServer::entitySciptChanging(const EntityItemID& entityID, const bool reload) { +void EntityScriptServer::entityScriptChanging(const EntityItemID& entityID, const bool reload) { if (_entityViewer.getTree() && !_shuttingDown) { _entitiesScriptEngine->unloadEntityScript(entityID); checkAndCallPreload(entityID, reload); diff --git a/assignment-client/src/scripts/EntityScriptServer.h b/assignment-client/src/scripts/EntityScriptServer.h index 63b1418534..8429df3d6f 100644 --- a/assignment-client/src/scripts/EntityScriptServer.h +++ b/assignment-client/src/scripts/EntityScriptServer.h @@ -48,7 +48,7 @@ private: void shutdown(); void addingEntity(const EntityItemID& entityID); void deletingEntity(const EntityItemID& entityID); - void entitySciptChanging(const EntityItemID& entityID, const bool reload); + void entityScriptChanging(const EntityItemID& entityID, const bool reload); void checkAndCallPreload(const EntityItemID& entityID, const bool reload = false); bool _shuttingDown { false }; diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 0f61be291f..78d3f61047 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -196,7 +196,7 @@ void EntityTreeRenderer::init() { connect(entityTree.get(), &EntityTree::deletingEntity, this, &EntityTreeRenderer::deletingEntity, Qt::QueuedConnection); connect(entityTree.get(), &EntityTree::addingEntity, this, &EntityTreeRenderer::addingEntity, Qt::QueuedConnection); connect(entityTree.get(), &EntityTree::entityScriptChanging, - this, &EntityTreeRenderer::entitySciptChanging, Qt::QueuedConnection); + this, &EntityTreeRenderer::entityScriptChanging, Qt::QueuedConnection); } void EntityTreeRenderer::shutdown() { @@ -923,7 +923,7 @@ void EntityTreeRenderer::addEntityToScene(EntityItemPointer entity) { } -void EntityTreeRenderer::entitySciptChanging(const EntityItemID& entityID, const bool reload) { +void EntityTreeRenderer::entityScriptChanging(const EntityItemID& entityID, const bool reload) { if (_tree && !_shuttingDown) { _entitiesScriptEngine->unloadEntityScript(entityID); checkAndCallPreload(entityID, reload); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index 7890ae8275..8c021ad184 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -122,7 +122,7 @@ signals: public slots: void addingEntity(const EntityItemID& entityID); void deletingEntity(const EntityItemID& entityID); - void entitySciptChanging(const EntityItemID& entityID, const bool reload); + void entityScriptChanging(const EntityItemID& entityID, const bool reload); void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision); void updateEntityRenderStatus(bool shouldRenderEntities); void updateZone(const EntityItemID& id); diff --git a/libraries/ui/src/Tooltip.cpp b/libraries/ui/src/Tooltip.cpp index 94e04f34b6..c0c015e72f 100644 --- a/libraries/ui/src/Tooltip.cpp +++ b/libraries/ui/src/Tooltip.cpp @@ -114,7 +114,7 @@ void Tooltip::handleAPIResponse(QNetworkReply& requestReply) { if (_description.isEmpty()) { const QString DESCRIPTION_KEY = "description"; - // we have an empty description - did a non-empty desciption come back? + // we have an empty description - did a non-empty description come back? if (placeObject.contains(DESCRIPTION_KEY)) { QString placeDescription = placeObject[DESCRIPTION_KEY].toString(); From 97e9bfff368497f6305c0f2a4937cde28e9d03a7 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 17 Jan 2017 15:40:05 -0800 Subject: [PATCH 012/114] Remove Viewer API for entity server scripts --- assignment-client/src/scripts/EntityScriptServer.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index 010a827eb9..49e89ca9b2 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -158,8 +158,6 @@ void EntityScriptServer::resetEntitiesScriptEngine() { auto engineName = QString("Entities %1").arg(++_entitiesScriptEngineCount); auto newEngine = QSharedPointer(new ScriptEngine(NO_SCRIPT, engineName)); - newEngine->registerGlobalObject("EntityViewer", &_entityViewer); - auto webSocketServerConstructorValue = newEngine->newFunction(WebSocketServerClass::constructor); newEngine->globalObject().setProperty("WebSocketServer", webSocketServerConstructorValue); From 20b7bb0c5493e5136b7a3d272da628176151d8be Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 17 Jan 2017 16:41:56 -0800 Subject: [PATCH 013/114] EntityScriptServer tracks server scripts --- assignment-client/src/scripts/EntityScriptServer.cpp | 6 +++--- assignment-client/src/scripts/EntityScriptServer.h | 2 +- libraries/entities/src/EntityItem.h | 4 ++++ libraries/entities/src/EntityTree.cpp | 4 ++++ libraries/entities/src/EntityTree.h | 2 ++ libraries/entities/src/EntityTreeElement.cpp | 5 +++++ 6 files changed, 19 insertions(+), 4 deletions(-) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index 49e89ca9b2..a1635ff77c 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -97,7 +97,7 @@ void EntityScriptServer::run() { auto tree = _entityViewer.getTree().get(); connect(tree, &EntityTree::deletingEntity, this, &EntityScriptServer::deletingEntity, Qt::QueuedConnection); connect(tree, &EntityTree::addingEntity, this, &EntityScriptServer::addingEntity, Qt::QueuedConnection); - connect(tree, &EntityTree::entityScriptChanging, this, &EntityScriptServer::entityScriptChanging, Qt::QueuedConnection); + connect(tree, &EntityTree::entityServerScriptChanging, this, &EntityScriptServer::entityServerScriptChanging, Qt::QueuedConnection); } void EntityScriptServer::nodeActivated(SharedNodePointer activatedNode) { @@ -220,7 +220,7 @@ void EntityScriptServer::deletingEntity(const EntityItemID& entityID) { } } -void EntityScriptServer::entityScriptChanging(const EntityItemID& entityID, const bool reload) { +void EntityScriptServer::entityServerScriptChanging(const EntityItemID& entityID, const bool reload) { if (_entityViewer.getTree() && !_shuttingDown) { _entitiesScriptEngine->unloadEntityScript(entityID); checkAndCallPreload(entityID, reload); @@ -231,7 +231,7 @@ void EntityScriptServer::checkAndCallPreload(const EntityItemID& entityID, const if (_entityViewer.getTree() && !_shuttingDown) { EntityItemPointer entity = _entityViewer.getTree()->findEntityByEntityItemID(entityID); if (entity && entity->shouldPreloadScript() && _entitiesScriptEngine) { - QString scriptUrl = entity->getScript(); + QString scriptUrl = entity->getServerScripts(); scriptUrl = ResourceManager::normalizeURL(scriptUrl); ScriptEngine::loadEntityScript(_entitiesScriptEngine, entityID, scriptUrl, reload); entity->scriptHasPreloaded(); diff --git a/assignment-client/src/scripts/EntityScriptServer.h b/assignment-client/src/scripts/EntityScriptServer.h index 8429df3d6f..5c2c700097 100644 --- a/assignment-client/src/scripts/EntityScriptServer.h +++ b/assignment-client/src/scripts/EntityScriptServer.h @@ -48,7 +48,7 @@ private: void shutdown(); void addingEntity(const EntityItemID& entityID); void deletingEntity(const EntityItemID& entityID); - void entityScriptChanging(const EntityItemID& entityID, const bool reload); + void entityServerScriptChanging(const EntityItemID& entityID, const bool reload); void checkAndCallPreload(const EntityItemID& entityID, const bool reload = false); bool _shuttingDown { false }; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 505d90bb81..7e3514af54 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -444,6 +444,10 @@ public: ((_loadedScript != _script) || (_loadedScriptTimestamp != _scriptTimestamp)); } void scriptHasPreloaded() { _loadedScript = _script; _loadedScriptTimestamp = _scriptTimestamp; } + bool shouldPreloadServerScript() const { return !_script.isEmpty() && + ((_loadedScript != _script) || (_loadedScriptTimestamp != _scriptTimestamp)); } + void serverScriptHasPreloaded() { _loadedScript = _script; _loadedScriptTimestamp = _scriptTimestamp; } + bool getClientOnly() const { return _clientOnly; } void setClientOnly(bool clientOnly) { _clientOnly = clientOnly; } // if this entity is client-only, which avatar is it associated with? diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 4796dda671..38f413b0c5 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -394,6 +394,10 @@ void EntityTree::emitEntityScriptChanging(const EntityItemID& entityItemID, cons emit entityScriptChanging(entityItemID, reload); } +void EntityTree::emitEntityServerScriptChanging(const EntityItemID& entityItemID, const bool reload) { + emit entityServerScriptChanging(entityItemID, reload); +} + void EntityTree::notifyNewCollisionSoundURL(const QString& newURL, const EntityItemID& entityID) { emit newCollisionSoundURL(QUrl(newURL), entityID); } diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 98598b879b..5a0aa49f75 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -202,6 +202,7 @@ public: void entityChanged(EntityItemPointer entity); void emitEntityScriptChanging(const EntityItemID& entityItemID, const bool reload); + void emitEntityServerScriptChanging(const EntityItemID& entityItemID, const bool reload); void setSimulation(EntitySimulationPointer simulation); EntitySimulationPointer getSimulation() const { return _simulation; } @@ -270,6 +271,7 @@ signals: void deletingEntity(const EntityItemID& entityID); void addingEntity(const EntityItemID& entityID); void entityScriptChanging(const EntityItemID& entityItemID, const bool reload); + void entityServerScriptChanging(const EntityItemID& entityItemID, const bool reload); void newCollisionSoundURL(const QUrl& url, const EntityItemID& entityID); void clearingEntities(); diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index e374c6d289..22b70a82b8 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -925,6 +925,7 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int // 3) remember the old cube for the entity so we can mark it as dirty if (entityItem) { QString entityScriptBefore = entityItem->getScript(); + QString entityServerScriptsBefore = entityItem->getServerScripts(); quint64 entityScriptTimestampBefore = entityItem->getScriptTimestamp(); bool bestFitBefore = bestFitEntityBounds(entityItem); EntityTreeElementPointer currentContainingElement = _myTree->getContainingElement(entityItemID); @@ -948,6 +949,7 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int } QString entityScriptAfter = entityItem->getScript(); + QString entityServerScriptsAfter = entityItem->getServerScripts(); quint64 entityScriptTimestampAfter = entityItem->getScriptTimestamp(); bool reload = entityScriptTimestampBefore != entityScriptTimestampAfter; @@ -956,6 +958,9 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int if (entityScriptBefore != entityScriptAfter || reload) { _myTree->emitEntityScriptChanging(entityItemID, reload); // the entity script has changed } + if (entityServerScriptsBefore != entityServerScriptsAfter || reload) { + _myTree->emitEntityServerScriptChanging(entityItemID, reload); // the entity server script has changed + } } else { entityItem = EntityTypes::constructEntityItem(dataAt, bytesLeftToRead, args); From 8137c59ef7645e087e1b8d7182203ad5b0879a7d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 18 Jan 2017 11:15:29 -0800 Subject: [PATCH 014/114] Add support for sending requests to entity script server --- .../src/scripts/EntityScriptServer.cpp | 34 +++- .../src/scripts/EntityScriptServer.h | 3 + interface/src/Application.cpp | 6 +- .../entities/src/EntityScriptingInterface.cpp | 1 + .../networking/src/EntityScriptClient.cpp | 153 ++++++++++++++++++ libraries/networking/src/EntityScriptClient.h | 67 ++++++++ 6 files changed, 261 insertions(+), 3 deletions(-) create mode 100644 libraries/networking/src/EntityScriptClient.cpp create mode 100644 libraries/networking/src/EntityScriptClient.h diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index 58e1d1e71b..d93fda9f1a 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -25,6 +25,8 @@ #include "../entities/AssignmentParentFinder.h" +const size_t UUID_LENGTH_BYTES = 16; + int EntityScriptServer::_entitiesScriptEngineCount = 0; EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : ThreadedAssignment(message) { @@ -52,10 +54,39 @@ EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : ThreadedAssig packetReceiver.registerListener(PacketType::BulkAvatarData, avatarHashMap.data(), "processAvatarDataPacket"); packetReceiver.registerListener(PacketType::KillAvatar, avatarHashMap.data(), "processKillAvatar"); packetReceiver.registerListener(PacketType::AvatarIdentity, avatarHashMap.data(), "processAvatarIdentityPacket"); + + packetReceiver.registerListener(PacketType::ReloadEntityServerScript, this, "handleReloadEntityServerScriptPacket"); + packetReceiver.registerListener(PacketType::EntityScriptGetStatus, this, "handleEntityScriptGetStatusPacket"); } static const QString ENTITY_SCRIPT_SERVER_LOGGING_NAME = "entity-script-server"; +void EntityScriptServer::handleReloadEntityServerScriptPacket(QSharedPointer message, SharedNodePointer senderNode) { + auto entityID = QUuid::fromRfc4122(message->read(UUID_LENGTH_BYTES)); + + if (_entityViewer.getTree() && !_shuttingDown) { + qDebug() << "Reloading: " << entityID; + _entitiesScriptEngine->unloadEntityScript(entityID); + checkAndCallPreload(entityID, true); + } +} + +void EntityScriptServer::handleEntityScriptGetStatusPacket(QSharedPointer message, SharedNodePointer senderNode) { + MessageID messageID; + message->readPrimitive(&messageID); + auto entityID = QUuid::fromRfc4122(message->read(UUID_LENGTH_BYTES)); + + // TODO(Huffman) Get Status + + qDebug() << "Getting script status of: " << entityID; + auto replyPacket = NLPacket::create(PacketType::EntityScriptGetStatusReply, -1, true); + replyPacket->writePrimitive(messageID); + replyPacket->writeString("running"); + + auto nodeList = DependencyManager::get(); + nodeList->sendPacket(std::move(replyPacket), *senderNode); +} + void EntityScriptServer::run() { // make sure we request our script once the agent connects to the domain auto nodeList = DependencyManager::get(); @@ -75,7 +106,8 @@ void EntityScriptServer::run() { connect(nodeList.data(), &LimitedNodeList::nodeKilled, this, &EntityScriptServer::nodeKilled); nodeList->addSetOfNodeTypesToNodeInterestSet({ - NodeType::AudioMixer, NodeType::AvatarMixer, NodeType::EntityServer, NodeType::MessagesMixer, NodeType::AssetServer + NodeType::Agent, NodeType::AudioMixer, NodeType::AvatarMixer, + NodeType::EntityServer, NodeType::MessagesMixer, NodeType::AssetServer }); // Setup Script Engine diff --git a/assignment-client/src/scripts/EntityScriptServer.h b/assignment-client/src/scripts/EntityScriptServer.h index 63b1418534..d1b3363ecc 100644 --- a/assignment-client/src/scripts/EntityScriptServer.h +++ b/assignment-client/src/scripts/EntityScriptServer.h @@ -39,6 +39,9 @@ private slots: void handleJurisdictionPacket(QSharedPointer message, SharedNodePointer senderNode); void handleSelectedAudioFormat(QSharedPointer message); + void handleReloadEntityServerScriptPacket(QSharedPointer message, SharedNodePointer senderNode); + void handleEntityScriptGetStatusPacket(QSharedPointer message, SharedNodePointer senderNode); + private: void negotiateAudioFormat(); void selectAudioFormat(const QString& selectedCodecName); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4f35b10a1b..5d32a830d0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -61,7 +61,7 @@ #include #include #include -#include +#include #include #include #include @@ -173,6 +173,7 @@ #include "FrameTimingsScriptingInterface.h" #include #include +#include // On Windows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU // FIXME seems to be broken. @@ -514,6 +515,7 @@ bool setupEssentials(int& argc, char** argv) { DependencyManager::set(true, qApp, qApp); DependencyManager::set(); DependencyManager::set(); + DependencyManager::set(); return previousSessionCrashed; } @@ -852,7 +854,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // tell the NodeList instance who to tell the domain server we care about nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer - << NodeType::EntityServer << NodeType::AssetServer << NodeType::MessagesMixer); + << NodeType::EntityServer << NodeType::AssetServer << NodeType::MessagesMixer << NodeType::EntityScriptServer); // connect to the packet sent signal of the _entityEditSender connect(&_entityEditSender, &EntityEditPacketSender::packetSent, this, &Application::packetSent); diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index f90fddfc5a..c9ac379827 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -25,6 +25,7 @@ #include "QVariantGLM.h" #include "SimulationOwner.h" #include "ZoneEntityItem.h" +#include EntityScriptingInterface::EntityScriptingInterface(bool bidOnSimulationOwnership) : diff --git a/libraries/networking/src/EntityScriptClient.cpp b/libraries/networking/src/EntityScriptClient.cpp new file mode 100644 index 0000000000..2d4b493f11 --- /dev/null +++ b/libraries/networking/src/EntityScriptClient.cpp @@ -0,0 +1,153 @@ +#include "EntityScriptClient.h" +#include "NodeList.h" +#include "NetworkLogging.h" + +#include + +MessageID EntityScriptClient::_currentID = 0; + +GetScriptStatusRequest::GetScriptStatusRequest(QUuid entityID) : _entityID(entityID) { +} + +GetScriptStatusRequest::~GetScriptStatusRequest() { + +} + +void GetScriptStatusRequest::start() { + auto client = DependencyManager::get(); + qDebug() << "Sending script status request"; + client->getEntityServerScriptStatus(_entityID, [this](bool responseReceived) { + qDebug() << "Received script status request"; + emit finished(this); + }); +} + +EntityScriptClient::EntityScriptClient() { + setCustomDeleter([](Dependency* dependency){ + static_cast(dependency)->deleteLater(); + }); + + auto nodeList = DependencyManager::get(); + auto& packetReceiver = nodeList->getPacketReceiver(); + + packetReceiver.registerListener(PacketType::EntityScriptGetStatusReply, this, "handleGetScriptStatusReply"); + + connect(nodeList.data(), &LimitedNodeList::nodeKilled, this, &EntityScriptClient::handleNodeKilled); + connect(nodeList.data(), &LimitedNodeList::clientConnectionToNodeReset, + this, &EntityScriptClient::handleNodeClientConnectionReset); +} + +GetScriptStatusRequest* EntityScriptClient::createScriptStatusRequest(QUuid entityID) { + auto request = new GetScriptStatusRequest(entityID); + + request->moveToThread(thread()); + + return request; +} + +bool EntityScriptClient::reloadServerScript(QUuid entityID) { + // Send packet to entity script server + auto nodeList = DependencyManager::get(); + SharedNodePointer entityScriptServer = nodeList->soloNodeOfType(NodeType::EntityScriptServer); + + if (entityScriptServer) { + auto id = entityID.toRfc4122(); + auto payloadSize = id.size(); + auto packet = NLPacket::create(PacketType::ReloadEntityServerScript, payloadSize, true); + + packet->write(id); + + if (nodeList->sendPacket(std::move(packet), *entityScriptServer) != -1) { + return true; + } + } + + return false; +} + +MessageID EntityScriptClient::getEntityServerScriptStatus(QUuid entityID, GetScriptStatusCallback callback) { + auto nodeList = DependencyManager::get(); + SharedNodePointer entityScriptServer = nodeList->soloNodeOfType(NodeType::EntityScriptServer); + + if (entityScriptServer) { + auto packetList = NLPacketList::create(PacketType::EntityScriptGetStatus, QByteArray(), true, true); + + auto messageID = ++_currentID; + packetList->writePrimitive(messageID); + + packetList->write(entityID.toRfc4122()); + + if (nodeList->sendPacketList(std::move(packetList), *entityScriptServer) != -1) { + _pendingEntityScriptStatusRequests[entityScriptServer][messageID] = callback; + + return messageID; + } + } + + callback(false); + return INVALID_MESSAGE_ID; +} + +void EntityScriptClient::handleGetScriptStatusReply(QSharedPointer message, SharedNodePointer senderNode) { + Q_ASSERT(QThread::currentThread() == thread()); + + MessageID messageID; + message->readPrimitive(&messageID); + + auto status = message->readString(); + + // Check if we have any pending requests for this node + auto messageMapIt = _pendingEntityScriptStatusRequests.find(senderNode); + if (messageMapIt != _pendingEntityScriptStatusRequests.end()) { + + // Found the node, get the MessageID -> Callback map + auto& messageCallbackMap = messageMapIt->second; + + // Check if we have this pending request + auto requestIt = messageCallbackMap.find(messageID); + if (requestIt != messageCallbackMap.end()) { + auto callback = requestIt->second; + callback(true); + messageCallbackMap.erase(requestIt); + } + + // Although the messageCallbackMap may now be empty, we won't delete the node until we have disconnected from + // it to avoid constantly creating/deleting the map on subsequent requests. + } +} + +void EntityScriptClient::handleNodeKilled(SharedNodePointer node) { + Q_ASSERT(QThread::currentThread() == thread()); + + if (node->getType() != NodeType::EntityScriptServer) { + return; + } + + forceFailureOfPendingRequests(node); +} + +void EntityScriptClient::handleNodeClientConnectionReset(SharedNodePointer node) { + // a client connection to a Node was reset + // if it was an EntityScriptServer we need to cause anything pending to fail so it is re-attempted + + if (node->getType() != NodeType::EntityScriptServer) { + return; + } + + //qCDebug(entity_script_client) << "EntityScriptClient detected client connection reset handshake with Asset Server - failing any pending requests"; + + forceFailureOfPendingRequests(node); +} + +void EntityScriptClient::forceFailureOfPendingRequests(SharedNodePointer node) { + + { + auto messageMapIt = _pendingEntityScriptStatusRequests.find(node); + if (messageMapIt != _pendingEntityScriptStatusRequests.end()) { + for (const auto& value : messageMapIt->second) { + value.second(false); + } + messageMapIt->second.clear(); + } + } +} \ No newline at end of file diff --git a/libraries/networking/src/EntityScriptClient.h b/libraries/networking/src/EntityScriptClient.h new file mode 100644 index 0000000000..795ed3e530 --- /dev/null +++ b/libraries/networking/src/EntityScriptClient.h @@ -0,0 +1,67 @@ +// +// EntityScriptClient.h +// libraries/networking/src +// +// Created by Ryan Huffman on 2017/01/13 +// Copyright 2017 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_EntityScriptClient_h +#define hifi_EntityScriptClient_h + +#include "LimitedNodeList.h" +#include "ReceivedMessage.h" +#include "AssetUtils.h" + +#include +#include +#include + +using MessageID = uint32_t; + +using GetScriptStatusCallback = std::function; + +class GetScriptStatusRequest : public QObject { + Q_OBJECT +public: + GetScriptStatusRequest(QUuid); + ~GetScriptStatusRequest(); + + Q_INVOKABLE void start(); + +signals: + void finished(GetScriptStatusRequest* request); + +private: + QUuid _entityID; + MessageID _messageID; + QString status; +}; + +class EntityScriptClient : public QObject, public Dependency { + Q_OBJECT +public: + EntityScriptClient(); + + Q_INVOKABLE GetScriptStatusRequest* createScriptStatusRequest(QUuid entityID); + + bool reloadServerScript(QUuid entityID); + MessageID getEntityServerScriptStatus(QUuid entityID, GetScriptStatusCallback callback); + +private slots: + void handleNodeKilled(SharedNodePointer node); + void handleNodeClientConnectionReset(SharedNodePointer node); + + void handleGetScriptStatusReply(QSharedPointer message, SharedNodePointer senderNode); + +private: + static MessageID _currentID; + std::unordered_map> _pendingEntityScriptStatusRequests; + + void forceFailureOfPendingRequests(SharedNodePointer node); +}; + +#endif \ No newline at end of file From d85f27e9920f82de1d9b3b7926fca3f6259a9de6 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 18 Jan 2017 11:15:59 -0800 Subject: [PATCH 015/114] Add Entities.getServerScriptStatus --- .../entities/src/EntityScriptingInterface.cpp | 29 +++++++++---------- .../entities/src/EntityScriptingInterface.h | 1 + 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index c9ac379827..bba9347cff 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -672,23 +672,20 @@ RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersectionWorke } bool EntityScriptingInterface::reloadServerScripts(QUuid entityID) { - // Send packet to entity script server - auto nodeList = DependencyManager::get(); - SharedNodePointer entityScriptServer = nodeList->soloNodeOfType(NodeType::AssetServer); + auto client = DependencyManager::get(); + return client->reloadServerScript(entityID); +} - if (entityScriptServer) { - auto id = entityID.toByteArray(); - auto payloadSize = id.size(); - auto packet = NLPacket::create(PacketType::ReloadEntityServerScript, payloadSize, true); - - packet->write(id); - - if (nodeList->sendPacket(std::move(packet), *entityScriptServer) != -1) { - return true; - } - } - - return false; +bool EntityScriptingInterface::getServerScriptStatus(QUuid entityID, QScriptValue callback) { + auto client = DependencyManager::get(); + auto request = client->createScriptStatusRequest(entityID); + connect(request, &GetScriptStatusRequest::finished, callback.engine(), [callback](GetScriptStatusRequest* request) mutable { + QScriptValueList args { true }; + callback.call(QScriptValue(), args); + request->deleteLater(); + }); + request->start(); + return true; } void EntityScriptingInterface::setLightsArePickable(bool value) { diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 30739782ea..12fef968f9 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -211,6 +211,7 @@ public slots: Q_INVOKABLE RayToEntityIntersectionResult findRayIntersectionBlocking(const PickRay& ray, bool precisionPicking = false, const QScriptValue& entityIdsToInclude = QScriptValue(), const QScriptValue& entityIdsToDiscard = QScriptValue()); Q_INVOKABLE bool reloadServerScripts(QUuid entityID); + Q_INVOKABLE bool getServerScriptStatus(QUuid entityID, QScriptValue callback); Q_INVOKABLE void setLightsArePickable(bool value); Q_INVOKABLE bool getLightsArePickable() const; From 3b5b88e719d380b307920f40464ef1a233b86e50 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 18 Jan 2017 11:17:13 -0800 Subject: [PATCH 016/114] Move MessageID to AssetUtils --- libraries/networking/src/AssetClient.h | 4 ---- libraries/networking/src/AssetRequest.cpp | 4 ++-- libraries/networking/src/AssetRequest.h | 4 ++-- libraries/networking/src/AssetUtils.h | 2 ++ libraries/networking/src/MappingRequest.cpp | 10 +++++----- libraries/networking/src/MappingRequest.h | 2 +- libraries/networking/src/NetworkLogging.h | 1 + libraries/networking/src/udt/PacketHeaders.h | 2 ++ 8 files changed, 15 insertions(+), 14 deletions(-) diff --git a/libraries/networking/src/AssetClient.h b/libraries/networking/src/AssetClient.h index 10a88c0676..be1cafa232 100644 --- a/libraries/networking/src/AssetClient.h +++ b/libraries/networking/src/AssetClient.h @@ -22,10 +22,8 @@ #include "AssetUtils.h" #include "LimitedNodeList.h" -#include "NLPacket.h" #include "Node.h" #include "ReceivedMessage.h" -#include "ResourceCache.h" class GetMappingRequest; class SetMappingRequest; @@ -60,8 +58,6 @@ public: Q_INVOKABLE AssetUpload* createUpload(const QString& filename); Q_INVOKABLE AssetUpload* createUpload(const QByteArray& data); - static const MessageID INVALID_MESSAGE_ID = 0; - public slots: void init(); diff --git a/libraries/networking/src/AssetRequest.cpp b/libraries/networking/src/AssetRequest.cpp index 13caf87b8d..8d663933ca 100644 --- a/libraries/networking/src/AssetRequest.cpp +++ b/libraries/networking/src/AssetRequest.cpp @@ -77,7 +77,7 @@ void AssetRequest::start() { _assetInfoRequestID = assetClient->getAssetInfo(_hash, [this](bool responseReceived, AssetServerError serverError, AssetInfo info) { - _assetInfoRequestID = AssetClient::INVALID_MESSAGE_ID; + _assetInfoRequestID = INVALID_MESSAGE_ID; _info = info; @@ -119,7 +119,7 @@ void AssetRequest::start() { // If the request is dead, return return; } - _assetRequestID = AssetClient::INVALID_MESSAGE_ID; + _assetRequestID = INVALID_MESSAGE_ID; if (!responseReceived) { _error = NetworkError; diff --git a/libraries/networking/src/AssetRequest.h b/libraries/networking/src/AssetRequest.h index e5d9d119d7..1632a55336 100644 --- a/libraries/networking/src/AssetRequest.h +++ b/libraries/networking/src/AssetRequest.h @@ -64,8 +64,8 @@ private: QString _hash; QByteArray _data; int _numPendingRequests { 0 }; - MessageID _assetRequestID { AssetClient::INVALID_MESSAGE_ID }; - MessageID _assetInfoRequestID { AssetClient::INVALID_MESSAGE_ID }; + MessageID _assetRequestID { INVALID_MESSAGE_ID }; + MessageID _assetInfoRequestID { INVALID_MESSAGE_ID }; }; #endif diff --git a/libraries/networking/src/AssetUtils.h b/libraries/networking/src/AssetUtils.h index 9e508418ab..b0008271d2 100644 --- a/libraries/networking/src/AssetUtils.h +++ b/libraries/networking/src/AssetUtils.h @@ -27,6 +27,8 @@ using AssetHash = QString; using AssetMapping = std::map; using AssetPathList = QStringList; +const MessageID INVALID_MESSAGE_ID = 0; + const size_t SHA256_HASH_LENGTH = 32; const size_t SHA256_HASH_HEX_LENGTH = 64; const uint64_t MAX_UPLOAD_SIZE = 1000 * 1000 * 1000; // 1GB diff --git a/libraries/networking/src/MappingRequest.cpp b/libraries/networking/src/MappingRequest.cpp index 62a60c521b..810b5b376d 100644 --- a/libraries/networking/src/MappingRequest.cpp +++ b/libraries/networking/src/MappingRequest.cpp @@ -68,7 +68,7 @@ void GetMappingRequest::doStart() { _mappingRequestID = assetClient->getAssetMapping(_path, [this, assetClient](bool responseReceived, AssetServerError error, QSharedPointer message) { - _mappingRequestID = AssetClient::INVALID_MESSAGE_ID; + _mappingRequestID = INVALID_MESSAGE_ID; if (!responseReceived) { _error = NetworkError; } else { @@ -100,7 +100,7 @@ void GetAllMappingsRequest::doStart() { _mappingRequestID = assetClient->getAllAssetMappings( [this, assetClient](bool responseReceived, AssetServerError error, QSharedPointer message) { - _mappingRequestID = AssetClient::INVALID_MESSAGE_ID; + _mappingRequestID = INVALID_MESSAGE_ID; if (!responseReceived) { _error = NetworkError; @@ -152,7 +152,7 @@ void SetMappingRequest::doStart() { _mappingRequestID = assetClient->setAssetMapping(_path, _hash, [this, assetClient](bool responseReceived, AssetServerError error, QSharedPointer message) { - _mappingRequestID = AssetClient::INVALID_MESSAGE_ID; + _mappingRequestID = INVALID_MESSAGE_ID; if (!responseReceived) { _error = NetworkError; } else { @@ -195,7 +195,7 @@ void DeleteMappingsRequest::doStart() { _mappingRequestID = assetClient->deleteAssetMappings(_paths, [this, assetClient](bool responseReceived, AssetServerError error, QSharedPointer message) { - _mappingRequestID = AssetClient::INVALID_MESSAGE_ID; + _mappingRequestID = INVALID_MESSAGE_ID; if (!responseReceived) { _error = NetworkError; } else { @@ -237,7 +237,7 @@ void RenameMappingRequest::doStart() { _mappingRequestID = assetClient->renameAssetMapping(_oldPath, _newPath, [this, assetClient](bool responseReceived, AssetServerError error, QSharedPointer message) { - _mappingRequestID = AssetClient::INVALID_MESSAGE_ID; + _mappingRequestID = INVALID_MESSAGE_ID; if (!responseReceived) { _error = NetworkError; } else { diff --git a/libraries/networking/src/MappingRequest.h b/libraries/networking/src/MappingRequest.h index 274d9dbd19..85b68e2427 100644 --- a/libraries/networking/src/MappingRequest.h +++ b/libraries/networking/src/MappingRequest.h @@ -40,7 +40,7 @@ public: protected: Error _error { NoError }; - MessageID _mappingRequestID { AssetClient::INVALID_MESSAGE_ID }; + MessageID _mappingRequestID { INVALID_MESSAGE_ID }; private: virtual void doStart() = 0; diff --git a/libraries/networking/src/NetworkLogging.h b/libraries/networking/src/NetworkLogging.h index 30116ff405..518c600efe 100644 --- a/libraries/networking/src/NetworkLogging.h +++ b/libraries/networking/src/NetworkLogging.h @@ -17,6 +17,7 @@ Q_DECLARE_LOGGING_CATEGORY(resourceLog) Q_DECLARE_LOGGING_CATEGORY(networking) Q_DECLARE_LOGGING_CATEGORY(asset_client) +Q_DECLARE_LOGGING_CATEGORY(entity_script_client) Q_DECLARE_LOGGING_CATEGORY(messages_client) #endif // hifi_NetworkLogging_h diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 346263b312..8b9ba6d5fe 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -107,6 +107,8 @@ public: RequestsDomainListData, ExitingSpaceBubble, PerAvatarGainSet, + EntityScriptGetStatus, + EntityScriptGetStatusReply, ReloadEntityServerScript, LAST_PACKET_TYPE = ReloadEntityServerScript }; From ed68d5a7a221643067ab79d07c526faad0a45ce6 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Jan 2017 14:08:19 -0800 Subject: [PATCH 017/114] add JSON filter to OctreeQuery --- .../networking/src/udt/PacketHeaders.cpp | 2 + libraries/networking/src/udt/PacketHeaders.h | 1 + libraries/octree/src/OctreeQuery.cpp | 127 +++++++++++------- libraries/octree/src/OctreeQuery.h | 23 ++-- 4 files changed, 93 insertions(+), 60 deletions(-) diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 48a570d803..e2203389d0 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -49,6 +49,8 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::EntityEdit: case PacketType::EntityData: return VERSION_ENTITIES_SERVER_SCRIPTS; + case PacketType::EntityQuery: + return VERSION_ENTITIES_JSON_FILTER; case PacketType::AvatarIdentity: case PacketType::AvatarData: case PacketType::BulkAvatarData: diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 346263b312..bbeb1c3919 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -199,6 +199,7 @@ const PacketVersion VERSION_WEB_ENTITIES_SUPPORT_DPI = 63; const PacketVersion VERSION_ENTITIES_ARROW_ACTION = 64; const PacketVersion VERSION_ENTITIES_LAST_EDITED_BY = 65; const PacketVersion VERSION_ENTITIES_SERVER_SCRIPTS = 66; +const PacketVersion VERSION_ENTITIES_JSON_FILTER = 67; enum class AssetServerPacketVersion: PacketVersion { VegasCongestionControl = 19 diff --git a/libraries/octree/src/OctreeQuery.cpp b/libraries/octree/src/OctreeQuery.cpp index 60e4b5fb3a..658bc67ba9 100644 --- a/libraries/octree/src/OctreeQuery.cpp +++ b/libraries/octree/src/OctreeQuery.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include #include @@ -23,35 +25,27 @@ OctreeQuery::OctreeQuery() { int OctreeQuery::getBroadcastData(unsigned char* destinationBuffer) { unsigned char* bufferStart = destinationBuffer; - // TODO: DRY this up to a shared method - // that can pack any type given the number of bytes - // and return the number of bytes to push the pointer + // back a boolean (cut to 1 byte) to designate if this query uses the sent view frustum + memcpy(destinationBuffer, &_usesFrustum, sizeof(_usesFrustum)); + destinationBuffer += sizeof(_usesFrustum); + + if (_usesFrustum) { + // TODO: DRY this up to a shared method + // that can pack any type given the number of bytes + // and return the number of bytes to push the pointer + + // camera details + memcpy(destinationBuffer, &_cameraPosition, sizeof(_cameraPosition)); + destinationBuffer += sizeof(_cameraPosition); + destinationBuffer += packOrientationQuatToBytes(destinationBuffer, _cameraOrientation); + destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _cameraFov); + destinationBuffer += packFloatRatioToTwoByte(destinationBuffer, _cameraAspectRatio); + destinationBuffer += packClipValueToTwoByte(destinationBuffer, _cameraNearClip); + destinationBuffer += packClipValueToTwoByte(destinationBuffer, _cameraFarClip); + memcpy(destinationBuffer, &_cameraEyeOffsetPosition, sizeof(_cameraEyeOffsetPosition)); + destinationBuffer += sizeof(_cameraEyeOffsetPosition); + } - // camera details - memcpy(destinationBuffer, &_cameraPosition, sizeof(_cameraPosition)); - destinationBuffer += sizeof(_cameraPosition); - destinationBuffer += packOrientationQuatToBytes(destinationBuffer, _cameraOrientation); - destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _cameraFov); - destinationBuffer += packFloatRatioToTwoByte(destinationBuffer, _cameraAspectRatio); - destinationBuffer += packClipValueToTwoByte(destinationBuffer, _cameraNearClip); - destinationBuffer += packClipValueToTwoByte(destinationBuffer, _cameraFarClip); - memcpy(destinationBuffer, &_cameraEyeOffsetPosition, sizeof(_cameraEyeOffsetPosition)); - destinationBuffer += sizeof(_cameraEyeOffsetPosition); - - // bitMask of less than byte wide items - unsigned char bitItems = 0; - - // NOTE: we need to keep these here for new clients to talk to old servers. After we know that the clients and - // servers and clients have all been updated we could remove these bits. New servers will always force these - // features on old clients even if they don't ask for them. (which old clients will properly handle). New clients - // will always ask for these so that old servers will use these features. - setAtBit(bitItems, WANT_LOW_RES_MOVING_BIT); - setAtBit(bitItems, WANT_COLOR_AT_BIT); - setAtBit(bitItems, WANT_DELTA_AT_BIT); - setAtBit(bitItems, WANT_COMPRESSION); - - *destinationBuffer++ = bitItems; - // desired Max Octree PPS memcpy(destinationBuffer, &_maxQueryPPS, sizeof(_maxQueryPPS)); destinationBuffer += sizeof(_maxQueryPPS); @@ -67,6 +61,25 @@ int OctreeQuery::getBroadcastData(unsigned char* destinationBuffer) { memcpy(destinationBuffer, &_cameraCenterRadius, sizeof(_cameraCenterRadius)); destinationBuffer += sizeof(_cameraCenterRadius); + // create a QByteArray that holds the binary representation of the JSON parameters + QByteArray binaryParametersDocument; + + if (!_jsonParameters.isEmpty()) { + binaryParametersDocument = QJsonDocument(_jsonParameters).toBinaryData(); + } + + // write the size of the JSON parameters + uint16_t binaryParametersBytes = binaryParametersDocument.size(); + memcpy(destinationBuffer, &binaryParametersBytes, sizeof(binaryParametersBytes)); + destinationBuffer += sizeof(binaryParametersBytes); + + // pack the binary JSON parameters + // NOTE: for now we assume that the filters that will be set are all small enough that we will not have a packet > MTU + if (binaryParametersDocument.size() > 0) { + memcpy(destinationBuffer, binaryParametersDocument.data(), binaryParametersBytes); + destinationBuffer += binaryParametersBytes; + } + return destinationBuffer - bufferStart; } @@ -76,24 +89,22 @@ int OctreeQuery::parseData(ReceivedMessage& message) { const unsigned char* startPosition = reinterpret_cast(message.getRawMessage()); const unsigned char* sourceBuffer = startPosition; - // camera details - memcpy(&_cameraPosition, sourceBuffer, sizeof(_cameraPosition)); - sourceBuffer += sizeof(_cameraPosition); - sourceBuffer += unpackOrientationQuatFromBytes(sourceBuffer, _cameraOrientation); - sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*) sourceBuffer, &_cameraFov); - sourceBuffer += unpackFloatRatioFromTwoByte(sourceBuffer,_cameraAspectRatio); - sourceBuffer += unpackClipValueFromTwoByte(sourceBuffer,_cameraNearClip); - sourceBuffer += unpackClipValueFromTwoByte(sourceBuffer,_cameraFarClip); - memcpy(&_cameraEyeOffsetPosition, sourceBuffer, sizeof(_cameraEyeOffsetPosition)); - sourceBuffer += sizeof(_cameraEyeOffsetPosition); - - // optional feature flags - unsigned char bitItems = 0; - bitItems = (unsigned char)*sourceBuffer++; - - // NOTE: we used to use these bits to set feature request items if we need to extend the protocol with optional features - // do it here with... wantFeature= oneAtBit(bitItems, WANT_FEATURE_BIT); - Q_UNUSED(bitItems); + // check if this query uses a view frustum + memcpy(&_usesFrustum, sourceBuffer, sizeof(_usesFrustum)); + sourceBuffer += _usesFrustum; + + if (_usesFrustum) { + // unpack camera details + memcpy(&_cameraPosition, sourceBuffer, sizeof(_cameraPosition)); + sourceBuffer += sizeof(_cameraPosition); + sourceBuffer += unpackOrientationQuatFromBytes(sourceBuffer, _cameraOrientation); + sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*) sourceBuffer, &_cameraFov); + sourceBuffer += unpackFloatRatioFromTwoByte(sourceBuffer,_cameraAspectRatio); + sourceBuffer += unpackClipValueFromTwoByte(sourceBuffer,_cameraNearClip); + sourceBuffer += unpackClipValueFromTwoByte(sourceBuffer,_cameraFarClip); + memcpy(&_cameraEyeOffsetPosition, sourceBuffer, sizeof(_cameraEyeOffsetPosition)); + sourceBuffer += sizeof(_cameraEyeOffsetPosition); + } // desired Max Octree PPS memcpy(&_maxQueryPPS, sourceBuffer, sizeof(_maxQueryPPS)); @@ -106,13 +117,25 @@ int OctreeQuery::parseData(ReceivedMessage& message) { // desired boundaryLevelAdjust memcpy(&_boundaryLevelAdjust, sourceBuffer, sizeof(_boundaryLevelAdjust)); sourceBuffer += sizeof(_boundaryLevelAdjust); - - auto bytesRead = sourceBuffer - startPosition; - auto bytesLeft = message.getSize() - bytesRead; - if (bytesLeft >= (int)sizeof(_cameraCenterRadius)) { - memcpy(&_cameraCenterRadius, sourceBuffer, sizeof(_cameraCenterRadius)); - sourceBuffer += sizeof(_cameraCenterRadius); + + memcpy(&_cameraCenterRadius, sourceBuffer, sizeof(_cameraCenterRadius)); + sourceBuffer += sizeof(_cameraCenterRadius); + + // check if we have a packed JSON filter + uint16_t binaryParametersBytes; + memcpy(&binaryParametersBytes, sourceBuffer, sizeof(binaryParametersBytes)); + sourceBuffer += sizeof(binaryParametersBytes); + + if (binaryParametersBytes > 0) { + // unpack the binary JSON parameters + QByteArray binaryJSONParameters { binaryParametersBytes, 0 }; + memcpy(binaryJSONParameters.data(), sourceBuffer, binaryParametersBytes); + sourceBuffer += binaryParametersBytes; + + // grab the parameter object from the packed binary representation of JSON + _jsonParameters = QJsonDocument::fromBinaryData(binaryJSONParameters).object(); } + return sourceBuffer - startPosition; } diff --git a/libraries/octree/src/OctreeQuery.h b/libraries/octree/src/OctreeQuery.h index e446e1abc7..79285697a5 100644 --- a/libraries/octree/src/OctreeQuery.h +++ b/libraries/octree/src/OctreeQuery.h @@ -31,14 +31,10 @@ typedef unsigned long long quint64; #include #include +#include + #include -// First bitset -const int WANT_LOW_RES_MOVING_BIT = 0; -const int WANT_COLOR_AT_BIT = 1; -const int WANT_DELTA_AT_BIT = 2; -const int UNUSED_BIT_3 = 3; // unused... available for new feature -const int WANT_COMPRESSION = 4; // 5th bit class OctreeQuery : public NodeData { Q_OBJECT @@ -71,11 +67,18 @@ public: void setCameraFarClip(float farClip) { _cameraFarClip = farClip; } void setCameraEyeOffsetPosition(const glm::vec3& eyeOffsetPosition) { _cameraEyeOffsetPosition = eyeOffsetPosition; } void setCameraCenterRadius(float radius) { _cameraCenterRadius = radius; } - + + // getters/setters for JSON filter + QJsonObject getJSONParameters() { return _jsonParameters; } + void setJSONParameters(const QJsonObject& jsonParameters) { _jsonParameters = jsonParameters; } + // related to Octree Sending strategies int getMaxQueryPacketsPerSecond() const { return _maxQueryPPS; } float getOctreeSizeScale() const { return _octreeElementSizeScale; } int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; } + + bool getUsesFrustum() { return _usesFrustum; } + void setUsesFrustum(bool usesFrustum) { _usesFrustum = usesFrustum; } public slots: void setMaxQueryPacketsPerSecond(int maxQueryPPS) { _maxQueryPPS = maxQueryPPS; } @@ -97,7 +100,11 @@ protected: int _maxQueryPPS = DEFAULT_MAX_OCTREE_PPS; float _octreeElementSizeScale = DEFAULT_OCTREE_SIZE_SCALE; /// used for LOD calculations int _boundaryLevelAdjust = 0; /// used for LOD calculations - + + uint8_t _usesFrustum = true; + + QJsonObject _jsonParameters; + private: // privatize the copy constructor and assignment operator so they cannot be called OctreeQuery(const OctreeQuery&); From 6e6f2c50b8e64086059aacd788d82580b7265124 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Jan 2017 14:28:59 -0800 Subject: [PATCH 018/114] leverage OctreeQuery enhancements in EntityScriptServer/OHV --- assignment-client/src/scripts/EntityScriptServer.cpp | 8 ++++++++ libraries/octree/src/OctreeHeadlessViewer.h | 4 ++++ libraries/octree/src/OctreeQuery.cpp | 2 ++ libraries/octree/src/OctreeQuery.h | 2 ++ 4 files changed, 16 insertions(+) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index a1635ff77c..f17785d2ed 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -88,6 +88,14 @@ void EntityScriptServer::run() { _entityViewer.setJurisdictionListener(entityScriptingInterface->getJurisdictionListener()); _entityViewer.init(); + + // setup the JSON filter that asks for entities with a non-default serverScripts property + QJsonObject queryJSONParameters; + queryJSONParameters["serverScripts"] = OctreeQuery::NON_DEFAULT_FILTER; + + // setup the JSON parameters so that OctreeQuery does not use a frustum and uses our JSON filter + _entityViewer.setQueryUsesFrustum(false); + _entityViewer.setQueryJSONParameters(queryJSONParameters); entityScriptingInterface->setEntityTree(_entityViewer.getTree()); diff --git a/libraries/octree/src/OctreeHeadlessViewer.h b/libraries/octree/src/OctreeHeadlessViewer.h index b43dceeba6..9e5b458048 100644 --- a/libraries/octree/src/OctreeHeadlessViewer.h +++ b/libraries/octree/src/OctreeHeadlessViewer.h @@ -64,6 +64,10 @@ public slots: int getMaxPacketsPerSecond() const { return _maxPacketsPerSecond; } unsigned getOctreeElementsCount() const { return _tree->getOctreeElementsCount(); } + + // octree query adjustments + void setQueryUsesFrustum(bool queryUsesFrustum) { _octreeQuery.setUsesFrustum(queryUsesFrustum); } + void setQueryJSONParameters(QJsonObject queryJSONParameters) { _octreeQuery.setJSONParameters(queryJSONParameters); } private: JurisdictionListener* _jurisdictionListener = nullptr; diff --git a/libraries/octree/src/OctreeQuery.cpp b/libraries/octree/src/OctreeQuery.cpp index 658bc67ba9..72b0838223 100644 --- a/libraries/octree/src/OctreeQuery.cpp +++ b/libraries/octree/src/OctreeQuery.cpp @@ -17,6 +17,8 @@ #include "OctreeConstants.h" #include "OctreeQuery.h" +const QString OctreeQuery::NON_DEFAULT_FILTER = "+"; + OctreeQuery::OctreeQuery() { _maxQueryPPS = DEFAULT_MAX_OCTREE_PPS; diff --git a/libraries/octree/src/OctreeQuery.h b/libraries/octree/src/OctreeQuery.h index 79285697a5..cfd2edcf8a 100644 --- a/libraries/octree/src/OctreeQuery.h +++ b/libraries/octree/src/OctreeQuery.h @@ -42,6 +42,8 @@ class OctreeQuery : public NodeData { public: OctreeQuery(); virtual ~OctreeQuery() {} + + static const QString NON_DEFAULT_FILTER; int getBroadcastData(unsigned char* destinationBuffer); int parseData(ReceivedMessage& message) override; From f9f958aef1ab9756afcc2145a40cc8f477ad9675 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Jan 2017 14:31:15 -0800 Subject: [PATCH 019/114] provide direct access to OctreeQuery from OHV --- assignment-client/src/scripts/EntityScriptServer.cpp | 4 ++-- libraries/octree/src/OctreeHeadlessViewer.h | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index f17785d2ed..e542d5e8bf 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -94,8 +94,8 @@ void EntityScriptServer::run() { queryJSONParameters["serverScripts"] = OctreeQuery::NON_DEFAULT_FILTER; // setup the JSON parameters so that OctreeQuery does not use a frustum and uses our JSON filter - _entityViewer.setQueryUsesFrustum(false); - _entityViewer.setQueryJSONParameters(queryJSONParameters); + _entityViewer.getOctreeQuery().setUsesFrustum(false); + _entityViewer.getOctreeQuery().setJSONParameters(queryJSONParameters); entityScriptingInterface->setEntityTree(_entityViewer.getTree()); diff --git a/libraries/octree/src/OctreeHeadlessViewer.h b/libraries/octree/src/OctreeHeadlessViewer.h index 9e5b458048..a502844fa5 100644 --- a/libraries/octree/src/OctreeHeadlessViewer.h +++ b/libraries/octree/src/OctreeHeadlessViewer.h @@ -36,6 +36,8 @@ public: virtual void render(RenderArgs* renderArgs) override { /* swallow these */ } void setJurisdictionListener(JurisdictionListener* jurisdictionListener) { _jurisdictionListener = jurisdictionListener; } + + OctreeQuery& getOctreeQuery() { return _octreeQuery; } static int parseOctreeStats(QSharedPointer message, SharedNodePointer sourceNode); static void trackIncomingOctreePacket(const QByteArray& packet, const SharedNodePointer& sendingNode, bool wasStatsPacket); @@ -64,10 +66,6 @@ public slots: int getMaxPacketsPerSecond() const { return _maxPacketsPerSecond; } unsigned getOctreeElementsCount() const { return _tree->getOctreeElementsCount(); } - - // octree query adjustments - void setQueryUsesFrustum(bool queryUsesFrustum) { _octreeQuery.setUsesFrustum(queryUsesFrustum); } - void setQueryJSONParameters(QJsonObject queryJSONParameters) { _octreeQuery.setJSONParameters(queryJSONParameters); } private: JurisdictionListener* _jurisdictionListener = nullptr; From 3556379034cbadb4bfcf276ed2bcde9ee031a6ca Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Jan 2017 16:57:21 -0800 Subject: [PATCH 020/114] leverage JSON filter changes to OctreeQuery in EntityServer --- .../src/octree/OctreeQueryNode.cpp | 120 +++---- .../src/octree/OctreeSendThread.cpp | 8 +- .../src/scripts/EntityScriptServer.cpp | 3 +- libraries/entities/src/EntityItem.cpp | 19 ++ libraries/entities/src/EntityItem.h | 2 + .../entities/src/EntityItemProperties.cpp | 316 +++++++++--------- libraries/entities/src/EntityTree.h | 3 + libraries/entities/src/EntityTreeElement.cpp | 7 +- libraries/entities/src/EntityTreeElement.h | 1 - libraries/octree/src/Octree.h | 6 +- libraries/octree/src/OctreeConstants.h | 2 +- libraries/octree/src/OctreeElement.h | 2 +- libraries/octree/src/OctreeQuery.cpp | 3 - libraries/octree/src/OctreeQuery.h | 2 - 14 files changed, 265 insertions(+), 229 deletions(-) diff --git a/assignment-client/src/octree/OctreeQueryNode.cpp b/assignment-client/src/octree/OctreeQueryNode.cpp index fa844dc0f8..6b0536e31d 100644 --- a/assignment-client/src/octree/OctreeQueryNode.cpp +++ b/assignment-client/src/octree/OctreeQueryNode.cpp @@ -156,65 +156,71 @@ bool OctreeQueryNode::updateCurrentViewFrustum() { if (_isShuttingDown) { return false; } - - bool currentViewFrustumChanged = false; - ViewFrustum newestViewFrustum; - // get position and orientation details from the camera - newestViewFrustum.setPosition(getCameraPosition()); - newestViewFrustum.setOrientation(getCameraOrientation()); - - newestViewFrustum.setCenterRadius(getCameraCenterRadius()); - - // Also make sure it's got the correct lens details from the camera - float originalFOV = getCameraFov(); - float wideFOV = originalFOV + VIEW_FRUSTUM_FOV_OVERSEND; - - if (0.0f != getCameraAspectRatio() && - 0.0f != getCameraNearClip() && - 0.0f != getCameraFarClip() && - getCameraNearClip() != getCameraFarClip()) { - newestViewFrustum.setProjection(glm::perspective( - glm::radians(wideFOV), // hack - getCameraAspectRatio(), - getCameraNearClip(), - getCameraFarClip())); - } - - - { // if there has been a change, then recalculate - QMutexLocker viewLocker(&_viewMutex); - if (!newestViewFrustum.isVerySimilar(_currentViewFrustum)) { - _currentViewFrustum = newestViewFrustum; - _currentViewFrustum.calculate(); - currentViewFrustumChanged = true; - } - } - - // Also check for LOD changes from the client - if (_lodInitialized) { - if (_lastClientBoundaryLevelAdjust != getBoundaryLevelAdjust()) { - _lastClientBoundaryLevelAdjust = getBoundaryLevelAdjust(); - _lodChanged = true; - } - if (_lastClientOctreeSizeScale != getOctreeSizeScale()) { - _lastClientOctreeSizeScale = getOctreeSizeScale(); - _lodChanged = true; - } + + if (_usesFrustum) { + // this client does not use a view frustum so the view frustum for this query has not changed + return false; } else { - _lodInitialized = true; - _lastClientOctreeSizeScale = getOctreeSizeScale(); - _lastClientBoundaryLevelAdjust = getBoundaryLevelAdjust(); - _lodChanged = false; + bool currentViewFrustumChanged = false; + + ViewFrustum newestViewFrustum; + // get position and orientation details from the camera + newestViewFrustum.setPosition(getCameraPosition()); + newestViewFrustum.setOrientation(getCameraOrientation()); + + newestViewFrustum.setCenterRadius(getCameraCenterRadius()); + + // Also make sure it's got the correct lens details from the camera + float originalFOV = getCameraFov(); + float wideFOV = originalFOV + VIEW_FRUSTUM_FOV_OVERSEND; + + if (0.0f != getCameraAspectRatio() && + 0.0f != getCameraNearClip() && + 0.0f != getCameraFarClip() && + getCameraNearClip() != getCameraFarClip()) { + newestViewFrustum.setProjection(glm::perspective( + glm::radians(wideFOV), // hack + getCameraAspectRatio(), + getCameraNearClip(), + getCameraFarClip())); + } + + + { // if there has been a change, then recalculate + QMutexLocker viewLocker(&_viewMutex); + if (!newestViewFrustum.isVerySimilar(_currentViewFrustum)) { + _currentViewFrustum = newestViewFrustum; + _currentViewFrustum.calculate(); + currentViewFrustumChanged = true; + } + } + + // Also check for LOD changes from the client + if (_lodInitialized) { + if (_lastClientBoundaryLevelAdjust != getBoundaryLevelAdjust()) { + _lastClientBoundaryLevelAdjust = getBoundaryLevelAdjust(); + _lodChanged = true; + } + if (_lastClientOctreeSizeScale != getOctreeSizeScale()) { + _lastClientOctreeSizeScale = getOctreeSizeScale(); + _lodChanged = true; + } + } else { + _lodInitialized = true; + _lastClientOctreeSizeScale = getOctreeSizeScale(); + _lastClientBoundaryLevelAdjust = getBoundaryLevelAdjust(); + _lodChanged = false; + } + + // When we first detect that the view stopped changing, we record this. + // but we don't change it back to false until we've completely sent this + // scene. + if (_viewFrustumChanging && !currentViewFrustumChanged) { + _viewFrustumJustStoppedChanging = true; + } + _viewFrustumChanging = currentViewFrustumChanged; + return currentViewFrustumChanged; } - - // When we first detect that the view stopped changing, we record this. - // but we don't change it back to false until we've completely sent this - // scene. - if (_viewFrustumChanging && !currentViewFrustumChanged) { - _viewFrustumJustStoppedChanging = true; - } - _viewFrustumChanging = currentViewFrustumChanged; - return currentViewFrustumChanged; } void OctreeQueryNode::setViewSent(bool viewSent) { diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 0fbaf978e2..68938887d7 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -316,8 +316,9 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode* int truePacketsSent = 0; int trueBytesSent = 0; int packetsSentThisInterval = 0; - bool isFullScene = ((!viewFrustumChanged) && nodeData->getViewFrustumJustStoppedChanging()) - || nodeData->hasLodChanged(); + bool isFullScene = !nodeData->getUsesFrustum() + || ((!viewFrustumChanged) && nodeData->getViewFrustumJustStoppedChanging()) + || nodeData->hasLodChanged(); bool somethingToSend = true; // assume we have something @@ -432,7 +433,8 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode* boundaryLevelAdjust, octreeSizeScale, nodeData->getLastTimeBagEmpty(), isFullScene, &nodeData->stats, _myServer->getJurisdiction(), - &nodeData->extraEncodeData); + &nodeData->extraEncodeData, + nodeData->getJSONParameters()); nodeData->copyCurrentViewFrustum(params.viewFrustum); if (viewFrustumChanged) { nodeData->copyLastKnownViewFrustum(params.lastViewFrustum); diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index e542d5e8bf..edb5f6126a 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -91,7 +91,8 @@ void EntityScriptServer::run() { // setup the JSON filter that asks for entities with a non-default serverScripts property QJsonObject queryJSONParameters; - queryJSONParameters["serverScripts"] = OctreeQuery::NON_DEFAULT_FILTER; + static const QString SERVER_SCRIPTS_PROPERTY = "serverScripts"; + queryJSONParameters[SERVER_SCRIPTS_PROPERTY] = EntityQueryFilterSymbol::NonDefault; // setup the JSON parameters so that OctreeQuery does not use a frustum and uses our JSON filter _entityViewer.getOctreeQuery().setUsesFrustum(false); diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index b640f7bd8d..cd9f31d887 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -2233,3 +2233,22 @@ void EntityItem::globalizeProperties(EntityItemProperties& properties, const QSt QUuid empty; properties.setParentID(empty); } + + +bool EntityItem::matchesJSONFilters(const QJsonObject& jsonFilters) const { + // currently the only property filter we handle is '+' which means that query is only asking for entities + // where the given property is non-default + + // enumerate the filter object - for each key present check if the filter (which we only expect to be '+' right now) + // tells us that we should include this entity or not + bool matchedAllFilters = true; + + for (auto& property : jsonFilters.keys()) { + if (jsonFilters[property] == EntityQueryFilterSymbol::NonDefault) { + // check if this entity has a non-default value for the given property + + } + } + + return matchedAllFilters; +} diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 7e3514af54..b82d3ac1cb 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -470,6 +470,8 @@ public: QUuid getLastEditedBy() const { return _lastEditedBy; } void setLastEditedBy(QUuid value) { _lastEditedBy = value; } + + bool matchesJSONFilters(const QJsonObject& jsonFilters) const; protected: diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index adc0fba1be..e934883db8 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -31,22 +31,169 @@ KeyLightPropertyGroup EntityItemProperties::_staticKeyLight; EntityPropertyList PROP_LAST_ITEM = (EntityPropertyList)(PROP_AFTER_LAST_ITEM - 1); +static QHash _propertyStringsToEnums; + EntityItemProperties::EntityItemProperties(EntityPropertyFlags desiredProperties) : + _id(UNKNOWN_ENTITY_ID), + _idSet(false), + _lastEdited(0), + _type(EntityTypes::Unknown), -_id(UNKNOWN_ENTITY_ID), -_idSet(false), -_lastEdited(0), -_type(EntityTypes::Unknown), + _localRenderAlpha(1.0f), -_localRenderAlpha(1.0f), + _localRenderAlphaChanged(false), -_localRenderAlphaChanged(false), - -_defaultSettings(true), -_naturalDimensions(1.0f, 1.0f, 1.0f), -_naturalPosition(0.0f, 0.0f, 0.0f), -_desiredProperties(desiredProperties) + _defaultSettings(true), + _naturalDimensions(1.0f, 1.0f, 1.0f), + _naturalPosition(0.0f, 0.0f, 0.0f), + _desiredProperties(desiredProperties) { + static std::once_flag initMap; + + std::call_once(initMap, [](){ + ADD_PROPERTY_TO_MAP(PROP_VISIBLE, Visible, visible, bool); + ADD_PROPERTY_TO_MAP(PROP_POSITION, Position, position, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_DIMENSIONS, Dimensions, dimensions, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_ROTATION, Rotation, rotation, glm::quat); + ADD_PROPERTY_TO_MAP(PROP_DENSITY, Density, density, float); + ADD_PROPERTY_TO_MAP(PROP_VELOCITY, Velocity, velocity, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_GRAVITY, Gravity, gravity, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_ACCELERATION, Acceleration, acceleration, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_DAMPING, Damping, damping, float); + ADD_PROPERTY_TO_MAP(PROP_RESTITUTION, Restitution, restitution, float); + ADD_PROPERTY_TO_MAP(PROP_FRICTION, Friction, friction, float); + ADD_PROPERTY_TO_MAP(PROP_LIFETIME, Lifetime, lifetime, float); + ADD_PROPERTY_TO_MAP(PROP_SCRIPT, Script, script, QString); + ADD_PROPERTY_TO_MAP(PROP_SCRIPT_TIMESTAMP, ScriptTimestamp, scriptTimestamp, quint64); + ADD_PROPERTY_TO_MAP(PROP_SERVER_SCRIPTS, ServerScripts, serverScripts, QString); + ADD_PROPERTY_TO_MAP(PROP_COLLISION_SOUND_URL, CollisionSoundURL, collisionSoundURL, QString); + ADD_PROPERTY_TO_MAP(PROP_COLOR, Color, color, xColor); + ADD_PROPERTY_TO_MAP(PROP_COLOR_SPREAD, ColorSpread, colorSpread, xColor); + ADD_PROPERTY_TO_MAP(PROP_COLOR_START, ColorStart, colorStart, xColor); + ADD_PROPERTY_TO_MAP(PROP_COLOR_FINISH, ColorFinish, colorFinish, xColor); + ADD_PROPERTY_TO_MAP(PROP_ALPHA, Alpha, alpha, float); + ADD_PROPERTY_TO_MAP(PROP_ALPHA_SPREAD, AlphaSpread, alphaSpread, float); + ADD_PROPERTY_TO_MAP(PROP_ALPHA_START, AlphaStart, alphaStart, float); + ADD_PROPERTY_TO_MAP(PROP_ALPHA_FINISH, AlphaFinish, alphaFinish, float); + ADD_PROPERTY_TO_MAP(PROP_EMITTER_SHOULD_TRAIL, EmitterShouldTrail, emitterShouldTrail, bool); + ADD_PROPERTY_TO_MAP(PROP_MODEL_URL, ModelURL, modelURL, QString); + ADD_PROPERTY_TO_MAP(PROP_COMPOUND_SHAPE_URL, CompoundShapeURL, compoundShapeURL, QString); + ADD_PROPERTY_TO_MAP(PROP_REGISTRATION_POINT, RegistrationPoint, registrationPoint, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_ANGULAR_VELOCITY, AngularVelocity, angularVelocity, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_ANGULAR_DAMPING, AngularDamping, angularDamping, float); + ADD_PROPERTY_TO_MAP(PROP_COLLISIONLESS, Collisionless, collisionless, bool); + ADD_PROPERTY_TO_MAP(PROP_DYNAMIC, unused, ignoreForCollisions, unused); // legacy support + ADD_PROPERTY_TO_MAP(PROP_COLLISION_MASK, unused, collisionMask, unused); + ADD_PROPERTY_TO_MAP(PROP_COLLISION_MASK, unused, collidesWith, unused); + ADD_PROPERTY_TO_MAP(PROP_DYNAMIC, unused, collisionsWillMove, unused); // legacy support + ADD_PROPERTY_TO_MAP(PROP_DYNAMIC, unused, dynamic, unused); + ADD_PROPERTY_TO_MAP(PROP_IS_SPOTLIGHT, IsSpotlight, isSpotlight, bool); + ADD_PROPERTY_TO_MAP(PROP_INTENSITY, Intensity, intensity, float); + ADD_PROPERTY_TO_MAP(PROP_FALLOFF_RADIUS, FalloffRadius, falloffRadius, float); + ADD_PROPERTY_TO_MAP(PROP_EXPONENT, Exponent, exponent, float); + ADD_PROPERTY_TO_MAP(PROP_CUTOFF, Cutoff, cutoff, float); + ADD_PROPERTY_TO_MAP(PROP_LOCKED, Locked, locked, bool); + ADD_PROPERTY_TO_MAP(PROP_TEXTURES, Textures, textures, QString); + ADD_PROPERTY_TO_MAP(PROP_USER_DATA, UserData, userData, QString); + ADD_PROPERTY_TO_MAP(PROP_SIMULATION_OWNER, SimulationOwner, simulationOwner, SimulationOwner); + ADD_PROPERTY_TO_MAP(PROP_TEXT, Text, text, QString); + ADD_PROPERTY_TO_MAP(PROP_LINE_HEIGHT, LineHeight, lineHeight, float); + ADD_PROPERTY_TO_MAP(PROP_TEXT_COLOR, TextColor, textColor, xColor); + ADD_PROPERTY_TO_MAP(PROP_BACKGROUND_COLOR, BackgroundColor, backgroundColor, xColor); + ADD_PROPERTY_TO_MAP(PROP_SHAPE_TYPE, ShapeType, shapeType, ShapeType); + ADD_PROPERTY_TO_MAP(PROP_MAX_PARTICLES, MaxParticles, maxParticles, quint32); + ADD_PROPERTY_TO_MAP(PROP_LIFESPAN, Lifespan, lifespan, float); + ADD_PROPERTY_TO_MAP(PROP_EMITTING_PARTICLES, IsEmitting, isEmitting, bool); + ADD_PROPERTY_TO_MAP(PROP_EMIT_RATE, EmitRate, emitRate, float); + ADD_PROPERTY_TO_MAP(PROP_EMIT_SPEED, EmitSpeed, emitSpeed, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_SPEED_SPREAD, SpeedSpread, speedSpread, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_EMIT_ORIENTATION, EmitOrientation, emitOrientation, glm::quat); + ADD_PROPERTY_TO_MAP(PROP_EMIT_DIMENSIONS, EmitDimensions, emitDimensions, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_EMIT_RADIUS_START, EmitRadiusStart, emitRadiusStart, float); + ADD_PROPERTY_TO_MAP(PROP_POLAR_START, EmitPolarStart, polarStart, float); + ADD_PROPERTY_TO_MAP(PROP_POLAR_FINISH, EmitPolarFinish, polarFinish, float); + ADD_PROPERTY_TO_MAP(PROP_AZIMUTH_START, EmitAzimuthStart, azimuthStart, float); + ADD_PROPERTY_TO_MAP(PROP_AZIMUTH_FINISH, EmitAzimuthFinish, azimuthFinish, float); + ADD_PROPERTY_TO_MAP(PROP_EMIT_ACCELERATION, EmitAcceleration, emitAcceleration, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_ACCELERATION_SPREAD, AccelerationSpread, accelerationSpread, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_PARTICLE_RADIUS, ParticleRadius, particleRadius, float); + ADD_PROPERTY_TO_MAP(PROP_RADIUS_SPREAD, RadiusSpread, radiusSpread, float); + ADD_PROPERTY_TO_MAP(PROP_RADIUS_START, RadiusStart, radiusStart, float); + ADD_PROPERTY_TO_MAP(PROP_RADIUS_FINISH, RadiusFinish, radiusFinish, float); + ADD_PROPERTY_TO_MAP(PROP_MARKETPLACE_ID, MarketplaceID, marketplaceID, QString); + ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_COLOR, KeyLightColor, keyLightColor, xColor); + ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_INTENSITY, KeyLightIntensity, keyLightIntensity, float); + ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_AMBIENT_INTENSITY, KeyLightAmbientIntensity, keyLightAmbientIntensity, float); + ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_DIRECTION, KeyLightDirection, keyLightDirection, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_VOXEL_VOLUME_SIZE, VoxelVolumeSize, voxelVolumeSize, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_VOXEL_DATA, VoxelData, voxelData, QByteArray); + ADD_PROPERTY_TO_MAP(PROP_VOXEL_SURFACE_STYLE, VoxelSurfaceStyle, voxelSurfaceStyle, uint16_t); + ADD_PROPERTY_TO_MAP(PROP_NAME, Name, name, QString); + ADD_PROPERTY_TO_MAP(PROP_BACKGROUND_MODE, BackgroundMode, backgroundMode, BackgroundMode); + ADD_PROPERTY_TO_MAP(PROP_SOURCE_URL, SourceUrl, sourceUrl, QString); + ADD_PROPERTY_TO_MAP(PROP_LINE_WIDTH, LineWidth, lineWidth, float); + ADD_PROPERTY_TO_MAP(PROP_LINE_POINTS, LinePoints, linePoints, QVector); + ADD_PROPERTY_TO_MAP(PROP_HREF, Href, href, QString); + ADD_PROPERTY_TO_MAP(PROP_DESCRIPTION, Description, description, QString); + ADD_PROPERTY_TO_MAP(PROP_FACE_CAMERA, FaceCamera, faceCamera, bool); + ADD_PROPERTY_TO_MAP(PROP_ACTION_DATA, ActionData, actionData, QByteArray); + ADD_PROPERTY_TO_MAP(PROP_NORMALS, Normals, normals, QVector); + ADD_PROPERTY_TO_MAP(PROP_STROKE_WIDTHS, StrokeWidths, strokeWidths, QVector); + ADD_PROPERTY_TO_MAP(PROP_X_TEXTURE_URL, XTextureURL, xTextureURL, QString); + ADD_PROPERTY_TO_MAP(PROP_Y_TEXTURE_URL, YTextureURL, yTextureURL, QString); + ADD_PROPERTY_TO_MAP(PROP_Z_TEXTURE_URL, ZTextureURL, zTextureURL, QString); + ADD_PROPERTY_TO_MAP(PROP_X_N_NEIGHBOR_ID, XNNeighborID, xNNeighborID, EntityItemID); + ADD_PROPERTY_TO_MAP(PROP_Y_N_NEIGHBOR_ID, YNNeighborID, yNNeighborID, EntityItemID); + ADD_PROPERTY_TO_MAP(PROP_Z_N_NEIGHBOR_ID, ZNNeighborID, zNNeighborID, EntityItemID); + ADD_PROPERTY_TO_MAP(PROP_X_P_NEIGHBOR_ID, XPNeighborID, xPNeighborID, EntityItemID); + ADD_PROPERTY_TO_MAP(PROP_Y_P_NEIGHBOR_ID, YPNeighborID, yPNeighborID, EntityItemID); + ADD_PROPERTY_TO_MAP(PROP_Z_P_NEIGHBOR_ID, ZPNeighborID, zPNeighborID, EntityItemID); + + ADD_PROPERTY_TO_MAP(PROP_PARENT_ID, ParentID, parentID, QUuid); + ADD_PROPERTY_TO_MAP(PROP_PARENT_JOINT_INDEX, ParentJointIndex, parentJointIndex, uint16_t); + + ADD_PROPERTY_TO_MAP(PROP_LOCAL_POSITION, LocalPosition, localPosition, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_LOCAL_ROTATION, LocalRotation, localRotation, glm::quat); + ADD_PROPERTY_TO_MAP(PROP_LOCAL_VELOCITY, LocalVelocity, localVelocity, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_LOCAL_ANGULAR_VELOCITY, LocalAngularVelocity, localAngularVelocity, glm::vec3); + + ADD_PROPERTY_TO_MAP(PROP_JOINT_ROTATIONS_SET, JointRotationsSet, jointRotationsSet, QVector); + ADD_PROPERTY_TO_MAP(PROP_JOINT_ROTATIONS, JointRotations, jointRotations, QVector); + ADD_PROPERTY_TO_MAP(PROP_JOINT_TRANSLATIONS_SET, JointTranslationsSet, jointTranslationsSet, QVector); + ADD_PROPERTY_TO_MAP(PROP_JOINT_TRANSLATIONS, JointTranslations, jointTranslations, QVector); + + ADD_PROPERTY_TO_MAP(PROP_SHAPE, Shape, shape, QString); + + ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_URL, Animation, animation, URL, url); + ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_FPS, Animation, animation, FPS, fps); + ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_FRAME_INDEX, Animation, animation, CurrentFrame, currentFrame); + ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_PLAYING, Animation, animation, Running, running); + ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_LOOP, Animation, animation, Loop, loop); + ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_FIRST_FRAME, Animation, animation, FirstFrame, firstFrame); + ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_LAST_FRAME, Animation, animation, LastFrame, lastFrame); + ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_HOLD, Animation, animation, Hold, hold); + + ADD_GROUP_PROPERTY_TO_MAP(PROP_SKYBOX_COLOR, Skybox, skybox, Color, color); + ADD_GROUP_PROPERTY_TO_MAP(PROP_SKYBOX_URL, Skybox, skybox, URL, url); + + ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_SUN_MODEL_ENABLED, Stage, stage, SunModelEnabled, sunModelEnabled); + ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_LATITUDE, Stage, stage, Latitude, latitude); + ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_LONGITUDE, Stage, stage, Longitude, longitude); + ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_ALTITUDE, Stage, stage, Altitude, altitude); + ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_DAY, Stage, stage, Day, day); + ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_HOUR, Stage, stage, Hour, hour); + ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_AUTOMATIC_HOURDAY, Stage, stage, AutomaticHourDay, automaticHourDay); + + ADD_PROPERTY_TO_MAP(PROP_FLYING_ALLOWED, FlyingAllowed, flyingAllowed, bool); + ADD_PROPERTY_TO_MAP(PROP_GHOSTING_ALLOWED, GhostingAllowed, ghostingAllowed, bool); + + ADD_PROPERTY_TO_MAP(PROP_DPI, DPI, dpi, uint16_t); + + // FIXME - these are not yet handled + //ADD_PROPERTY_TO_MAP(PROP_CREATED, Created, created, quint64); + + }); + } void EntityItemProperties::setSittingPoints(const QVector& sittingPoints) { @@ -917,154 +1064,7 @@ QScriptValue EntityItemProperties::entityPropertyFlagsToScriptValue(QScriptEngin return result; } -static QHash _propertyStringsToEnums; - void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue& object, EntityPropertyFlags& flags) { - static std::once_flag initMap; - - std::call_once(initMap, [](){ - ADD_PROPERTY_TO_MAP(PROP_VISIBLE, Visible, visible, bool); - ADD_PROPERTY_TO_MAP(PROP_POSITION, Position, position, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_DIMENSIONS, Dimensions, dimensions, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_ROTATION, Rotation, rotation, glm::quat); - ADD_PROPERTY_TO_MAP(PROP_DENSITY, Density, density, float); - ADD_PROPERTY_TO_MAP(PROP_VELOCITY, Velocity, velocity, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_GRAVITY, Gravity, gravity, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_ACCELERATION, Acceleration, acceleration, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_DAMPING, Damping, damping, float); - ADD_PROPERTY_TO_MAP(PROP_RESTITUTION, Restitution, restitution, float); - ADD_PROPERTY_TO_MAP(PROP_FRICTION, Friction, friction, float); - ADD_PROPERTY_TO_MAP(PROP_LIFETIME, Lifetime, lifetime, float); - ADD_PROPERTY_TO_MAP(PROP_SCRIPT, Script, script, QString); - ADD_PROPERTY_TO_MAP(PROP_SCRIPT_TIMESTAMP, ScriptTimestamp, scriptTimestamp, quint64); - ADD_PROPERTY_TO_MAP(PROP_SERVER_SCRIPTS, ServerScripts, serverScripts, QString); - ADD_PROPERTY_TO_MAP(PROP_COLLISION_SOUND_URL, CollisionSoundURL, collisionSoundURL, QString); - ADD_PROPERTY_TO_MAP(PROP_COLOR, Color, color, xColor); - ADD_PROPERTY_TO_MAP(PROP_COLOR_SPREAD, ColorSpread, colorSpread, xColor); - ADD_PROPERTY_TO_MAP(PROP_COLOR_START, ColorStart, colorStart, xColor); - ADD_PROPERTY_TO_MAP(PROP_COLOR_FINISH, ColorFinish, colorFinish, xColor); - ADD_PROPERTY_TO_MAP(PROP_ALPHA, Alpha, alpha, float); - ADD_PROPERTY_TO_MAP(PROP_ALPHA_SPREAD, AlphaSpread, alphaSpread, float); - ADD_PROPERTY_TO_MAP(PROP_ALPHA_START, AlphaStart, alphaStart, float); - ADD_PROPERTY_TO_MAP(PROP_ALPHA_FINISH, AlphaFinish, alphaFinish, float); - ADD_PROPERTY_TO_MAP(PROP_EMITTER_SHOULD_TRAIL, EmitterShouldTrail, emitterShouldTrail, bool); - ADD_PROPERTY_TO_MAP(PROP_MODEL_URL, ModelURL, modelURL, QString); - ADD_PROPERTY_TO_MAP(PROP_COMPOUND_SHAPE_URL, CompoundShapeURL, compoundShapeURL, QString); - ADD_PROPERTY_TO_MAP(PROP_REGISTRATION_POINT, RegistrationPoint, registrationPoint, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_ANGULAR_VELOCITY, AngularVelocity, angularVelocity, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_ANGULAR_DAMPING, AngularDamping, angularDamping, float); - ADD_PROPERTY_TO_MAP(PROP_COLLISIONLESS, Collisionless, collisionless, bool); - ADD_PROPERTY_TO_MAP(PROP_DYNAMIC, unused, ignoreForCollisions, unused); // legacy support - ADD_PROPERTY_TO_MAP(PROP_COLLISION_MASK, unused, collisionMask, unused); - ADD_PROPERTY_TO_MAP(PROP_COLLISION_MASK, unused, collidesWith, unused); - ADD_PROPERTY_TO_MAP(PROP_DYNAMIC, unused, collisionsWillMove, unused); // legacy support - ADD_PROPERTY_TO_MAP(PROP_DYNAMIC, unused, dynamic, unused); - ADD_PROPERTY_TO_MAP(PROP_IS_SPOTLIGHT, IsSpotlight, isSpotlight, bool); - ADD_PROPERTY_TO_MAP(PROP_INTENSITY, Intensity, intensity, float); - ADD_PROPERTY_TO_MAP(PROP_FALLOFF_RADIUS, FalloffRadius, falloffRadius, float); - ADD_PROPERTY_TO_MAP(PROP_EXPONENT, Exponent, exponent, float); - ADD_PROPERTY_TO_MAP(PROP_CUTOFF, Cutoff, cutoff, float); - ADD_PROPERTY_TO_MAP(PROP_LOCKED, Locked, locked, bool); - ADD_PROPERTY_TO_MAP(PROP_TEXTURES, Textures, textures, QString); - ADD_PROPERTY_TO_MAP(PROP_USER_DATA, UserData, userData, QString); - ADD_PROPERTY_TO_MAP(PROP_SIMULATION_OWNER, SimulationOwner, simulationOwner, SimulationOwner); - ADD_PROPERTY_TO_MAP(PROP_TEXT, Text, text, QString); - ADD_PROPERTY_TO_MAP(PROP_LINE_HEIGHT, LineHeight, lineHeight, float); - ADD_PROPERTY_TO_MAP(PROP_TEXT_COLOR, TextColor, textColor, xColor); - ADD_PROPERTY_TO_MAP(PROP_BACKGROUND_COLOR, BackgroundColor, backgroundColor, xColor); - ADD_PROPERTY_TO_MAP(PROP_SHAPE_TYPE, ShapeType, shapeType, ShapeType); - ADD_PROPERTY_TO_MAP(PROP_MAX_PARTICLES, MaxParticles, maxParticles, quint32); - ADD_PROPERTY_TO_MAP(PROP_LIFESPAN, Lifespan, lifespan, float); - ADD_PROPERTY_TO_MAP(PROP_EMITTING_PARTICLES, IsEmitting, isEmitting, bool); - ADD_PROPERTY_TO_MAP(PROP_EMIT_RATE, EmitRate, emitRate, float); - ADD_PROPERTY_TO_MAP(PROP_EMIT_SPEED, EmitSpeed, emitSpeed, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_SPEED_SPREAD, SpeedSpread, speedSpread, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_EMIT_ORIENTATION, EmitOrientation, emitOrientation, glm::quat); - ADD_PROPERTY_TO_MAP(PROP_EMIT_DIMENSIONS, EmitDimensions, emitDimensions, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_EMIT_RADIUS_START, EmitRadiusStart, emitRadiusStart, float); - ADD_PROPERTY_TO_MAP(PROP_POLAR_START, EmitPolarStart, polarStart, float); - ADD_PROPERTY_TO_MAP(PROP_POLAR_FINISH, EmitPolarFinish, polarFinish, float); - ADD_PROPERTY_TO_MAP(PROP_AZIMUTH_START, EmitAzimuthStart, azimuthStart, float); - ADD_PROPERTY_TO_MAP(PROP_AZIMUTH_FINISH, EmitAzimuthFinish, azimuthFinish, float); - ADD_PROPERTY_TO_MAP(PROP_EMIT_ACCELERATION, EmitAcceleration, emitAcceleration, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_ACCELERATION_SPREAD, AccelerationSpread, accelerationSpread, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_PARTICLE_RADIUS, ParticleRadius, particleRadius, float); - ADD_PROPERTY_TO_MAP(PROP_RADIUS_SPREAD, RadiusSpread, radiusSpread, float); - ADD_PROPERTY_TO_MAP(PROP_RADIUS_START, RadiusStart, radiusStart, float); - ADD_PROPERTY_TO_MAP(PROP_RADIUS_FINISH, RadiusFinish, radiusFinish, float); - ADD_PROPERTY_TO_MAP(PROP_MARKETPLACE_ID, MarketplaceID, marketplaceID, QString); - ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_COLOR, KeyLightColor, keyLightColor, xColor); - ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_INTENSITY, KeyLightIntensity, keyLightIntensity, float); - ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_AMBIENT_INTENSITY, KeyLightAmbientIntensity, keyLightAmbientIntensity, float); - ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_DIRECTION, KeyLightDirection, keyLightDirection, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_VOXEL_VOLUME_SIZE, VoxelVolumeSize, voxelVolumeSize, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_VOXEL_DATA, VoxelData, voxelData, QByteArray); - ADD_PROPERTY_TO_MAP(PROP_VOXEL_SURFACE_STYLE, VoxelSurfaceStyle, voxelSurfaceStyle, uint16_t); - ADD_PROPERTY_TO_MAP(PROP_NAME, Name, name, QString); - ADD_PROPERTY_TO_MAP(PROP_BACKGROUND_MODE, BackgroundMode, backgroundMode, BackgroundMode); - ADD_PROPERTY_TO_MAP(PROP_SOURCE_URL, SourceUrl, sourceUrl, QString); - ADD_PROPERTY_TO_MAP(PROP_LINE_WIDTH, LineWidth, lineWidth, float); - ADD_PROPERTY_TO_MAP(PROP_LINE_POINTS, LinePoints, linePoints, QVector); - ADD_PROPERTY_TO_MAP(PROP_HREF, Href, href, QString); - ADD_PROPERTY_TO_MAP(PROP_DESCRIPTION, Description, description, QString); - ADD_PROPERTY_TO_MAP(PROP_FACE_CAMERA, FaceCamera, faceCamera, bool); - ADD_PROPERTY_TO_MAP(PROP_ACTION_DATA, ActionData, actionData, QByteArray); - ADD_PROPERTY_TO_MAP(PROP_NORMALS, Normals, normals, QVector); - ADD_PROPERTY_TO_MAP(PROP_STROKE_WIDTHS, StrokeWidths, strokeWidths, QVector); - ADD_PROPERTY_TO_MAP(PROP_X_TEXTURE_URL, XTextureURL, xTextureURL, QString); - ADD_PROPERTY_TO_MAP(PROP_Y_TEXTURE_URL, YTextureURL, yTextureURL, QString); - ADD_PROPERTY_TO_MAP(PROP_Z_TEXTURE_URL, ZTextureURL, zTextureURL, QString); - ADD_PROPERTY_TO_MAP(PROP_X_N_NEIGHBOR_ID, XNNeighborID, xNNeighborID, EntityItemID); - ADD_PROPERTY_TO_MAP(PROP_Y_N_NEIGHBOR_ID, YNNeighborID, yNNeighborID, EntityItemID); - ADD_PROPERTY_TO_MAP(PROP_Z_N_NEIGHBOR_ID, ZNNeighborID, zNNeighborID, EntityItemID); - ADD_PROPERTY_TO_MAP(PROP_X_P_NEIGHBOR_ID, XPNeighborID, xPNeighborID, EntityItemID); - ADD_PROPERTY_TO_MAP(PROP_Y_P_NEIGHBOR_ID, YPNeighborID, yPNeighborID, EntityItemID); - ADD_PROPERTY_TO_MAP(PROP_Z_P_NEIGHBOR_ID, ZPNeighborID, zPNeighborID, EntityItemID); - - ADD_PROPERTY_TO_MAP(PROP_PARENT_ID, ParentID, parentID, QUuid); - ADD_PROPERTY_TO_MAP(PROP_PARENT_JOINT_INDEX, ParentJointIndex, parentJointIndex, uint16_t); - - ADD_PROPERTY_TO_MAP(PROP_LOCAL_POSITION, LocalPosition, localPosition, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_LOCAL_ROTATION, LocalRotation, localRotation, glm::quat); - ADD_PROPERTY_TO_MAP(PROP_LOCAL_VELOCITY, LocalVelocity, localVelocity, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_LOCAL_ANGULAR_VELOCITY, LocalAngularVelocity, localAngularVelocity, glm::vec3); - - ADD_PROPERTY_TO_MAP(PROP_JOINT_ROTATIONS_SET, JointRotationsSet, jointRotationsSet, QVector); - ADD_PROPERTY_TO_MAP(PROP_JOINT_ROTATIONS, JointRotations, jointRotations, QVector); - ADD_PROPERTY_TO_MAP(PROP_JOINT_TRANSLATIONS_SET, JointTranslationsSet, jointTranslationsSet, QVector); - ADD_PROPERTY_TO_MAP(PROP_JOINT_TRANSLATIONS, JointTranslations, jointTranslations, QVector); - - ADD_PROPERTY_TO_MAP(PROP_SHAPE, Shape, shape, QString); - - ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_URL, Animation, animation, URL, url); - ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_FPS, Animation, animation, FPS, fps); - ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_FRAME_INDEX, Animation, animation, CurrentFrame, currentFrame); - ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_PLAYING, Animation, animation, Running, running); - ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_LOOP, Animation, animation, Loop, loop); - ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_FIRST_FRAME, Animation, animation, FirstFrame, firstFrame); - ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_LAST_FRAME, Animation, animation, LastFrame, lastFrame); - ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_HOLD, Animation, animation, Hold, hold); - - ADD_GROUP_PROPERTY_TO_MAP(PROP_SKYBOX_COLOR, Skybox, skybox, Color, color); - ADD_GROUP_PROPERTY_TO_MAP(PROP_SKYBOX_URL, Skybox, skybox, URL, url); - - ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_SUN_MODEL_ENABLED, Stage, stage, SunModelEnabled, sunModelEnabled); - ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_LATITUDE, Stage, stage, Latitude, latitude); - ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_LONGITUDE, Stage, stage, Longitude, longitude); - ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_ALTITUDE, Stage, stage, Altitude, altitude); - ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_DAY, Stage, stage, Day, day); - ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_HOUR, Stage, stage, Hour, hour); - ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_AUTOMATIC_HOURDAY, Stage, stage, AutomaticHourDay, automaticHourDay); - - ADD_PROPERTY_TO_MAP(PROP_FLYING_ALLOWED, FlyingAllowed, flyingAllowed, bool); - ADD_PROPERTY_TO_MAP(PROP_GHOSTING_ALLOWED, GhostingAllowed, ghostingAllowed, bool); - - ADD_PROPERTY_TO_MAP(PROP_DPI, DPI, dpi, uint16_t); - - // FIXME - these are not yet handled - //ADD_PROPERTY_TO_MAP(PROP_CREATED, Created, created, quint64); - - }); if (object.isString()) { // TODO: figure out how to do this without a double lookup in the map diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 5a0aa49f75..35aae904cd 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -31,6 +31,9 @@ using ModelWeakPointer = std::weak_ptr; class EntitySimulation; +namespace EntityQueryFilterSymbol { + static const QString NonDefault = "+"; +} class NewlyCreatedEntityHook { public: diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 22b70a82b8..974d4d0be1 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -94,7 +94,7 @@ void EntityTreeElement::initializeExtraEncodeData(EncodeBitstreamParams& params) bool EntityTreeElement::shouldIncludeChildData(int childIndex, EncodeBitstreamParams& params) const { OctreeElementExtraEncodeData* extraEncodeData = params.extraEncodeData; assert(extraEncodeData); // EntityTrees always require extra encode data on their encoding passes - + if (extraEncodeData->contains(this)) { EntityTreeElementExtraEncodeDataPointer entityTreeElementExtraEncodeData = std::static_pointer_cast((*extraEncodeData)[this]); @@ -290,6 +290,11 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData if (!params.forceSendScene && entity->getLastChangedOnServer() < params.lastViewFrustumSent) { includeThisEntity = false; } + + if (!params.jsonFilters.isEmpty()) { + // if params include JSON filters, check if this entity matches + includeThisEntity = entity->matchesJSONFilters(params.jsonFilters); + } if (hadElementExtraData) { includeThisEntity = includeThisEntity && diff --git a/libraries/entities/src/EntityTreeElement.h b/libraries/entities/src/EntityTreeElement.h index 5b45846a74..aee8c7cfd6 100644 --- a/libraries/entities/src/EntityTreeElement.h +++ b/libraries/entities/src/EntityTreeElement.h @@ -127,7 +127,6 @@ public: bool alreadyFullyEncoded(EncodeBitstreamParams& params) const; - /// Override to serialize the state of this element. This is used for persistance and for transmission across the network. virtual OctreeElement::AppendState appendElementData(OctreePacketData* packetData, EncodeBitstreamParams& params) const override; diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index 6894f0aa1a..4b0bf908d6 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -81,6 +82,7 @@ public: OctreeSceneStats* stats; JurisdictionMap* jurisdictionMap; OctreeElementExtraEncodeData* extraEncodeData; + QJsonObject jsonFilters; // output hints from the encode process typedef enum { @@ -108,7 +110,8 @@ public: bool forceSendScene = true, OctreeSceneStats* stats = IGNORE_SCENE_STATS, JurisdictionMap* jurisdictionMap = IGNORE_JURISDICTION_MAP, - OctreeElementExtraEncodeData* extraEncodeData = NULL) : + OctreeElementExtraEncodeData* extraEncodeData = NULL, + QJsonObject jsonFilters = QJsonObject()) : lastViewFrustumSent(lastViewFrustumSent), maxEncodeLevel(maxEncodeLevel), maxLevelReached(0), @@ -121,6 +124,7 @@ public: stats(stats), jurisdictionMap(jurisdictionMap), extraEncodeData(extraEncodeData), + jsonFilters(jsonFilters), stopReason(UNKNOWN) { lastViewFrustum.invalidate(); diff --git a/libraries/octree/src/OctreeConstants.h b/libraries/octree/src/OctreeConstants.h index ea1ea63353..53442f52d6 100644 --- a/libraries/octree/src/OctreeConstants.h +++ b/libraries/octree/src/OctreeConstants.h @@ -12,7 +12,7 @@ #ifndef hifi_OctreeConstants_h #define hifi_OctreeConstants_h -#include // for quint64 +#include // for quint64/QString #include const quint64 CHANGE_FUDGE = 1000 * 200; // useconds of fudge in determining if we want to resend changed voxels diff --git a/libraries/octree/src/OctreeElement.h b/libraries/octree/src/OctreeElement.h index 61211a40d8..350ec9e5fa 100644 --- a/libraries/octree/src/OctreeElement.h +++ b/libraries/octree/src/OctreeElement.h @@ -108,7 +108,7 @@ public: virtual bool isRendered() const { return getShouldRender(); } virtual bool deleteApproved() const { return true; } - + virtual bool canRayIntersect() const { return isLeaf(); } /// \param center center of sphere in meters /// \param radius radius of sphere in meters diff --git a/libraries/octree/src/OctreeQuery.cpp b/libraries/octree/src/OctreeQuery.cpp index 72b0838223..73fe777646 100644 --- a/libraries/octree/src/OctreeQuery.cpp +++ b/libraries/octree/src/OctreeQuery.cpp @@ -17,9 +17,6 @@ #include "OctreeConstants.h" #include "OctreeQuery.h" -const QString OctreeQuery::NON_DEFAULT_FILTER = "+"; - - OctreeQuery::OctreeQuery() { _maxQueryPPS = DEFAULT_MAX_OCTREE_PPS; } diff --git a/libraries/octree/src/OctreeQuery.h b/libraries/octree/src/OctreeQuery.h index cfd2edcf8a..79285697a5 100644 --- a/libraries/octree/src/OctreeQuery.h +++ b/libraries/octree/src/OctreeQuery.h @@ -42,8 +42,6 @@ class OctreeQuery : public NodeData { public: OctreeQuery(); virtual ~OctreeQuery() {} - - static const QString NON_DEFAULT_FILTER; int getBroadcastData(unsigned char* destinationBuffer); int parseData(ReceivedMessage& message) override; From a1ad496772caf0fcd2fb34fb530228464ae1f629 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Jan 2017 17:19:47 -0800 Subject: [PATCH 021/114] handle match on non-default serverScripts property during entity send --- libraries/entities/src/EntityItem.cpp | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index cd9f31d887..f9038fd547 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -2236,19 +2236,27 @@ void EntityItem::globalizeProperties(EntityItemProperties& properties, const QSt bool EntityItem::matchesJSONFilters(const QJsonObject& jsonFilters) const { - // currently the only property filter we handle is '+' which means that query is only asking for entities - // where the given property is non-default - // enumerate the filter object - for each key present check if the filter (which we only expect to be '+' right now) - // tells us that we should include this entity or not - bool matchedAllFilters = true; + // The intention for the query JSON filter and this method is to be flexible to handle a variety of filters for + // ALL entity properties. Some work will need to be done to the property system so that it can be more flexible + // (to grab the value and default value of a property given the string representation of that property, for example) + + // currently the only property filter we handle is '+' for serverScripts + // which means that we only handle a filtered query asking for entities where the serverScripts property is non-default + + static const QString SERVER_SCRIPTS_PROPERTY = "serverScripts"; for (auto& property : jsonFilters.keys()) { - if (jsonFilters[property] == EntityQueryFilterSymbol::NonDefault) { - // check if this entity has a non-default value for the given property - + if (property == SERVER_SCRIPTS_PROPERTY && jsonFilters[property] == EntityQueryFilterSymbol::NonDefault) { + // check if this entity has a non-default value for serverScripts + if (_serverScripts != ENTITY_ITEM_DEFAULT_SERVER_SCRIPTS) { + return true; + } else { + return false; + } } } - return matchedAllFilters; + // the json filter syntax did not match what we expected, return a match + return true; } From b08bfe93f478c3d226e2e6e1278c0ef21bdeebf4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Jan 2017 17:25:26 -0800 Subject: [PATCH 022/114] change lastViewFrustumSent to lastQuerySent --- libraries/entities/src/EntityItem.h | 2 +- libraries/entities/src/EntityTreeElement.cpp | 4 ++-- libraries/entities/src/LightEntityItem.cpp | 2 +- libraries/entities/src/LineEntityItem.cpp | 2 +- libraries/entities/src/LineEntityItem.h | 2 +- libraries/entities/src/ModelEntityItem.cpp | 2 +- libraries/entities/src/ModelEntityItem.h | 2 +- libraries/entities/src/ParticleEffectEntityItem.cpp | 2 +- libraries/entities/src/PolyLineEntityItem.cpp | 2 +- libraries/entities/src/PolyLineEntityItem.h | 2 +- libraries/entities/src/PolyVoxEntityItem.cpp | 2 +- libraries/entities/src/PolyVoxEntityItem.h | 2 +- libraries/entities/src/ShapeEntityItem.cpp | 2 +- libraries/entities/src/TextEntityItem.cpp | 2 +- libraries/entities/src/TextEntityItem.h | 2 +- libraries/entities/src/WebEntityItem.cpp | 2 +- libraries/entities/src/WebEntityItem.h | 2 +- libraries/entities/src/ZoneEntityItem.cpp | 2 +- libraries/entities/src/ZoneEntityItem.h | 2 +- libraries/octree/src/Octree.cpp | 6 +++--- libraries/octree/src/Octree.h | 6 +++--- 21 files changed, 26 insertions(+), 26 deletions(-) diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index b82d3ac1cb..60afe38662 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -125,7 +125,7 @@ public: void markAsChangedOnServer() { _changedOnServer = usecTimestampNow(); } quint64 getLastChangedOnServer() const { return _changedOnServer; } - // TODO: eventually only include properties changed since the params.lastViewFrustumSent time + // TODO: eventually only include properties changed since the params.lastQuerySent time virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const; virtual OctreeElement::AppendState appendEntityData(OctreePacketData* packetData, EncodeBitstreamParams& params, diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 974d4d0be1..67a9265aa1 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -287,13 +287,13 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData EntityItemPointer entity = _entityItems[i]; bool includeThisEntity = true; - if (!params.forceSendScene && entity->getLastChangedOnServer() < params.lastViewFrustumSent) { + if (!params.forceSendScene && entity->getLastChangedOnServer() < params.lastQuerySent) { includeThisEntity = false; } if (!params.jsonFilters.isEmpty()) { // if params include JSON filters, check if this entity matches - includeThisEntity = entity->matchesJSONFilters(params.jsonFilters); + includeThisEntity = includeThisEntity && entity->matchesJSONFilters(params.jsonFilters); } if (hadElementExtraData) { diff --git a/libraries/entities/src/LightEntityItem.cpp b/libraries/entities/src/LightEntityItem.cpp index 1f78ddd598..e09822f028 100644 --- a/libraries/entities/src/LightEntityItem.cpp +++ b/libraries/entities/src/LightEntityItem.cpp @@ -174,7 +174,7 @@ int LightEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, } -// TODO: eventually only include properties changed since the params.lastViewFrustumSent time +// TODO: eventually only include properties changed since the params.lastQuerySent time EntityPropertyFlags LightEntityItem::getEntityProperties(EncodeBitstreamParams& params) const { EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); requestedProperties += PROP_IS_SPOTLIGHT; diff --git a/libraries/entities/src/LineEntityItem.cpp b/libraries/entities/src/LineEntityItem.cpp index 315de4938e..8ace665616 100644 --- a/libraries/entities/src/LineEntityItem.cpp +++ b/libraries/entities/src/LineEntityItem.cpp @@ -126,7 +126,7 @@ int LineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, } -// TODO: eventually only include properties changed since the params.lastViewFrustumSent time +// TODO: eventually only include properties changed since the params.lastQuerySent time EntityPropertyFlags LineEntityItem::getEntityProperties(EncodeBitstreamParams& params) const { EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); requestedProperties += PROP_COLOR; diff --git a/libraries/entities/src/LineEntityItem.h b/libraries/entities/src/LineEntityItem.h index fd0b38d16e..8629c94eb4 100644 --- a/libraries/entities/src/LineEntityItem.h +++ b/libraries/entities/src/LineEntityItem.h @@ -26,7 +26,7 @@ class LineEntityItem : public EntityItem { virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; virtual bool setProperties(const EntityItemProperties& properties) override; - // TODO: eventually only include properties changed since the params.lastViewFrustumSent time + // TODO: eventually only include properties changed since the params.lastQuerySent time virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 1f93973023..911ff224b2 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -160,7 +160,7 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, return bytesRead; } -// TODO: eventually only include properties changed since the params.lastViewFrustumSent time +// TODO: eventually only include properties changed since the params.lastQuerySent time EntityPropertyFlags ModelEntityItem::getEntityProperties(EncodeBitstreamParams& params) const { EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 07205e4ed6..e1cb5cd92c 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -29,7 +29,7 @@ public: virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; virtual bool setProperties(const EntityItemProperties& properties) override; - // TODO: eventually only include properties changed since the params.lastViewFrustumSent time + // TODO: eventually only include properties changed since the params.lastQuerySent time virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 392bd8acbe..140522b00e 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -469,7 +469,7 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch } -// TODO: eventually only include properties changed since the params.lastViewFrustumSent time +// TODO: eventually only include properties changed since the params.lastQuerySent time EntityPropertyFlags ParticleEffectEntityItem::getEntityProperties(EncodeBitstreamParams& params) const { EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); diff --git a/libraries/entities/src/PolyLineEntityItem.cpp b/libraries/entities/src/PolyLineEntityItem.cpp index 4cd59488c2..7abafad627 100644 --- a/libraries/entities/src/PolyLineEntityItem.cpp +++ b/libraries/entities/src/PolyLineEntityItem.cpp @@ -170,7 +170,7 @@ int PolyLineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* da } -// TODO: eventually only include properties changed since the params.lastViewFrustumSent time +// TODO: eventually only include properties changed since the params.lastQuerySent time EntityPropertyFlags PolyLineEntityItem::getEntityProperties(EncodeBitstreamParams& params) const { EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); requestedProperties += PROP_COLOR; diff --git a/libraries/entities/src/PolyLineEntityItem.h b/libraries/entities/src/PolyLineEntityItem.h index b4d107b777..5f9f9124cf 100644 --- a/libraries/entities/src/PolyLineEntityItem.h +++ b/libraries/entities/src/PolyLineEntityItem.h @@ -26,7 +26,7 @@ class PolyLineEntityItem : public EntityItem { virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; virtual bool setProperties(const EntityItemProperties& properties) override; - // TODO: eventually only include properties changed since the params.lastViewFrustumSent time + // TODO: eventually only include properties changed since the params.lastQuerySent time virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, diff --git a/libraries/entities/src/PolyVoxEntityItem.cpp b/libraries/entities/src/PolyVoxEntityItem.cpp index 958b3ff88c..2a374c1d17 100644 --- a/libraries/entities/src/PolyVoxEntityItem.cpp +++ b/libraries/entities/src/PolyVoxEntityItem.cpp @@ -179,7 +179,7 @@ int PolyVoxEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* dat } -// TODO: eventually only include properties changed since the params.lastViewFrustumSent time +// TODO: eventually only include properties changed since the params.lastQuerySent time EntityPropertyFlags PolyVoxEntityItem::getEntityProperties(EncodeBitstreamParams& params) const { EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); requestedProperties += PROP_VOXEL_VOLUME_SIZE; diff --git a/libraries/entities/src/PolyVoxEntityItem.h b/libraries/entities/src/PolyVoxEntityItem.h index 260384ce62..4f478c8bf7 100644 --- a/libraries/entities/src/PolyVoxEntityItem.h +++ b/libraries/entities/src/PolyVoxEntityItem.h @@ -26,7 +26,7 @@ class PolyVoxEntityItem : public EntityItem { virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; virtual bool setProperties(const EntityItemProperties& properties) override; - // TODO: eventually only include properties changed since the params.lastViewFrustumSent time + // TODO: eventually only include properties changed since the params.lastQuerySent time virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index 0dd54f7740..eaef4c5c0e 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -137,7 +137,7 @@ int ShapeEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, } -// TODO: eventually only include properties changed since the params.lastViewFrustumSent time +// TODO: eventually only include properties changed since the params.lastQuerySent time EntityPropertyFlags ShapeEntityItem::getEntityProperties(EncodeBitstreamParams& params) const { EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); requestedProperties += PROP_SHAPE; diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index dd6e083efd..fbb0bdc9cf 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -99,7 +99,7 @@ int TextEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, } -// TODO: eventually only include properties changed since the params.lastViewFrustumSent time +// TODO: eventually only include properties changed since the params.lastQuerySent time EntityPropertyFlags TextEntityItem::getEntityProperties(EncodeBitstreamParams& params) const { EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); requestedProperties += PROP_TEXT; diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index 0f031efd57..633aa96bfa 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -30,7 +30,7 @@ public: virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; virtual bool setProperties(const EntityItemProperties& properties) override; - // TODO: eventually only include properties changed since the params.lastViewFrustumSent time + // TODO: eventually only include properties changed since the params.lastQuerySent time virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, diff --git a/libraries/entities/src/WebEntityItem.cpp b/libraries/entities/src/WebEntityItem.cpp index 735ec1812a..ad0caf55cb 100644 --- a/libraries/entities/src/WebEntityItem.cpp +++ b/libraries/entities/src/WebEntityItem.cpp @@ -84,7 +84,7 @@ int WebEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, i } -// TODO: eventually only include properties changed since the params.lastViewFrustumSent time +// TODO: eventually only include properties changed since the params.lastQuerySent time EntityPropertyFlags WebEntityItem::getEntityProperties(EncodeBitstreamParams& params) const { EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); requestedProperties += PROP_SOURCE_URL; diff --git a/libraries/entities/src/WebEntityItem.h b/libraries/entities/src/WebEntityItem.h index a1f3564951..202a8fb93f 100644 --- a/libraries/entities/src/WebEntityItem.h +++ b/libraries/entities/src/WebEntityItem.h @@ -29,7 +29,7 @@ public: virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; virtual bool setProperties(const EntityItemProperties& properties) override; - // TODO: eventually only include properties changed since the params.lastViewFrustumSent time + // TODO: eventually only include properties changed since the params.lastQuerySent time virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, diff --git a/libraries/entities/src/ZoneEntityItem.cpp b/libraries/entities/src/ZoneEntityItem.cpp index 39496575ad..3e21497d63 100644 --- a/libraries/entities/src/ZoneEntityItem.cpp +++ b/libraries/entities/src/ZoneEntityItem.cpp @@ -133,7 +133,7 @@ int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, } -// TODO: eventually only include properties changed since the params.lastViewFrustumSent time +// TODO: eventually only include properties changed since the params.lastQuerySent time EntityPropertyFlags ZoneEntityItem::getEntityProperties(EncodeBitstreamParams& params) const { EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); diff --git a/libraries/entities/src/ZoneEntityItem.h b/libraries/entities/src/ZoneEntityItem.h index 3e816fc094..3084d71f46 100644 --- a/libraries/entities/src/ZoneEntityItem.h +++ b/libraries/entities/src/ZoneEntityItem.h @@ -30,7 +30,7 @@ public: virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; virtual bool setProperties(const EntityItemProperties& properties) override; - // TODO: eventually only include properties changed since the params.lastViewFrustumSent time + // TODO: eventually only include properties changed since the params.lastQuerySent time virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index d8c8229ce3..a19a9709dc 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -1077,7 +1077,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element, // If we were previously in the view, then we normally will return out of here and stop recursing. But // if we're in deltaView mode, and this element has changed since it was last sent, then we do // need to send it. - if (wasInView && !(params.deltaView && element->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE))) { + if (wasInView && !(params.deltaView && element->hasChangedSince(params.lastQuerySent - CHANGE_FUDGE))) { if (params.stats) { params.stats->skippedWasInView(element); } @@ -1088,7 +1088,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element, // If we're not in delta sending mode, and we weren't asked to do a force send, and the voxel hasn't changed, // then we can also bail early and save bits if (!params.forceSendScene && !params.deltaView && - !element->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE)) { + !element->hasChangedSince(params.lastQuerySent - CHANGE_FUDGE)) { if (params.stats) { params.stats->skippedNoChange(element); } @@ -1247,7 +1247,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element, // need to send it. if (!childWasInView || (params.deltaView && - childElement->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE))){ + childElement->hasChangedSince(params.lastQuerySent - CHANGE_FUDGE))){ childrenDataBits += (1 << (7 - originalIndex)); inViewWithColorCount++; diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index 4b0bf908d6..fa739f83a6 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -69,7 +69,7 @@ class EncodeBitstreamParams { public: ViewFrustum viewFrustum; ViewFrustum lastViewFrustum; - quint64 lastViewFrustumSent; + quint64 lastQuerySent; int maxEncodeLevel; int maxLevelReached; bool includeExistsBits; @@ -106,13 +106,13 @@ public: bool useDeltaView = false, int boundaryLevelAdjust = NO_BOUNDARY_ADJUST, float octreeElementSizeScale = DEFAULT_OCTREE_SIZE_SCALE, - quint64 lastViewFrustumSent = IGNORE_LAST_SENT, + quint64 lastQuerySent = IGNORE_LAST_SENT, bool forceSendScene = true, OctreeSceneStats* stats = IGNORE_SCENE_STATS, JurisdictionMap* jurisdictionMap = IGNORE_JURISDICTION_MAP, OctreeElementExtraEncodeData* extraEncodeData = NULL, QJsonObject jsonFilters = QJsonObject()) : - lastViewFrustumSent(lastViewFrustumSent), + lastQuerySent(lastQuerySent), maxEncodeLevel(maxEncodeLevel), maxLevelReached(0), includeExistsBits(includeExistsBits), From 5d1b53c600afa367d25e2298b03b855c05fe8fa7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Jan 2017 17:57:27 -0800 Subject: [PATCH 023/114] move map population with properties back --- .../entities/src/EntityItemProperties.cpp | 295 +++++++++--------- 1 file changed, 148 insertions(+), 147 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index e934883db8..572ca661a5 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -31,8 +31,6 @@ KeyLightPropertyGroup EntityItemProperties::_staticKeyLight; EntityPropertyList PROP_LAST_ITEM = (EntityPropertyList)(PROP_AFTER_LAST_ITEM - 1); -static QHash _propertyStringsToEnums; - EntityItemProperties::EntityItemProperties(EntityPropertyFlags desiredProperties) : _id(UNKNOWN_ENTITY_ID), _idSet(false), @@ -48,151 +46,6 @@ EntityItemProperties::EntityItemProperties(EntityPropertyFlags desiredProperties _naturalPosition(0.0f, 0.0f, 0.0f), _desiredProperties(desiredProperties) { - static std::once_flag initMap; - - std::call_once(initMap, [](){ - ADD_PROPERTY_TO_MAP(PROP_VISIBLE, Visible, visible, bool); - ADD_PROPERTY_TO_MAP(PROP_POSITION, Position, position, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_DIMENSIONS, Dimensions, dimensions, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_ROTATION, Rotation, rotation, glm::quat); - ADD_PROPERTY_TO_MAP(PROP_DENSITY, Density, density, float); - ADD_PROPERTY_TO_MAP(PROP_VELOCITY, Velocity, velocity, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_GRAVITY, Gravity, gravity, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_ACCELERATION, Acceleration, acceleration, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_DAMPING, Damping, damping, float); - ADD_PROPERTY_TO_MAP(PROP_RESTITUTION, Restitution, restitution, float); - ADD_PROPERTY_TO_MAP(PROP_FRICTION, Friction, friction, float); - ADD_PROPERTY_TO_MAP(PROP_LIFETIME, Lifetime, lifetime, float); - ADD_PROPERTY_TO_MAP(PROP_SCRIPT, Script, script, QString); - ADD_PROPERTY_TO_MAP(PROP_SCRIPT_TIMESTAMP, ScriptTimestamp, scriptTimestamp, quint64); - ADD_PROPERTY_TO_MAP(PROP_SERVER_SCRIPTS, ServerScripts, serverScripts, QString); - ADD_PROPERTY_TO_MAP(PROP_COLLISION_SOUND_URL, CollisionSoundURL, collisionSoundURL, QString); - ADD_PROPERTY_TO_MAP(PROP_COLOR, Color, color, xColor); - ADD_PROPERTY_TO_MAP(PROP_COLOR_SPREAD, ColorSpread, colorSpread, xColor); - ADD_PROPERTY_TO_MAP(PROP_COLOR_START, ColorStart, colorStart, xColor); - ADD_PROPERTY_TO_MAP(PROP_COLOR_FINISH, ColorFinish, colorFinish, xColor); - ADD_PROPERTY_TO_MAP(PROP_ALPHA, Alpha, alpha, float); - ADD_PROPERTY_TO_MAP(PROP_ALPHA_SPREAD, AlphaSpread, alphaSpread, float); - ADD_PROPERTY_TO_MAP(PROP_ALPHA_START, AlphaStart, alphaStart, float); - ADD_PROPERTY_TO_MAP(PROP_ALPHA_FINISH, AlphaFinish, alphaFinish, float); - ADD_PROPERTY_TO_MAP(PROP_EMITTER_SHOULD_TRAIL, EmitterShouldTrail, emitterShouldTrail, bool); - ADD_PROPERTY_TO_MAP(PROP_MODEL_URL, ModelURL, modelURL, QString); - ADD_PROPERTY_TO_MAP(PROP_COMPOUND_SHAPE_URL, CompoundShapeURL, compoundShapeURL, QString); - ADD_PROPERTY_TO_MAP(PROP_REGISTRATION_POINT, RegistrationPoint, registrationPoint, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_ANGULAR_VELOCITY, AngularVelocity, angularVelocity, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_ANGULAR_DAMPING, AngularDamping, angularDamping, float); - ADD_PROPERTY_TO_MAP(PROP_COLLISIONLESS, Collisionless, collisionless, bool); - ADD_PROPERTY_TO_MAP(PROP_DYNAMIC, unused, ignoreForCollisions, unused); // legacy support - ADD_PROPERTY_TO_MAP(PROP_COLLISION_MASK, unused, collisionMask, unused); - ADD_PROPERTY_TO_MAP(PROP_COLLISION_MASK, unused, collidesWith, unused); - ADD_PROPERTY_TO_MAP(PROP_DYNAMIC, unused, collisionsWillMove, unused); // legacy support - ADD_PROPERTY_TO_MAP(PROP_DYNAMIC, unused, dynamic, unused); - ADD_PROPERTY_TO_MAP(PROP_IS_SPOTLIGHT, IsSpotlight, isSpotlight, bool); - ADD_PROPERTY_TO_MAP(PROP_INTENSITY, Intensity, intensity, float); - ADD_PROPERTY_TO_MAP(PROP_FALLOFF_RADIUS, FalloffRadius, falloffRadius, float); - ADD_PROPERTY_TO_MAP(PROP_EXPONENT, Exponent, exponent, float); - ADD_PROPERTY_TO_MAP(PROP_CUTOFF, Cutoff, cutoff, float); - ADD_PROPERTY_TO_MAP(PROP_LOCKED, Locked, locked, bool); - ADD_PROPERTY_TO_MAP(PROP_TEXTURES, Textures, textures, QString); - ADD_PROPERTY_TO_MAP(PROP_USER_DATA, UserData, userData, QString); - ADD_PROPERTY_TO_MAP(PROP_SIMULATION_OWNER, SimulationOwner, simulationOwner, SimulationOwner); - ADD_PROPERTY_TO_MAP(PROP_TEXT, Text, text, QString); - ADD_PROPERTY_TO_MAP(PROP_LINE_HEIGHT, LineHeight, lineHeight, float); - ADD_PROPERTY_TO_MAP(PROP_TEXT_COLOR, TextColor, textColor, xColor); - ADD_PROPERTY_TO_MAP(PROP_BACKGROUND_COLOR, BackgroundColor, backgroundColor, xColor); - ADD_PROPERTY_TO_MAP(PROP_SHAPE_TYPE, ShapeType, shapeType, ShapeType); - ADD_PROPERTY_TO_MAP(PROP_MAX_PARTICLES, MaxParticles, maxParticles, quint32); - ADD_PROPERTY_TO_MAP(PROP_LIFESPAN, Lifespan, lifespan, float); - ADD_PROPERTY_TO_MAP(PROP_EMITTING_PARTICLES, IsEmitting, isEmitting, bool); - ADD_PROPERTY_TO_MAP(PROP_EMIT_RATE, EmitRate, emitRate, float); - ADD_PROPERTY_TO_MAP(PROP_EMIT_SPEED, EmitSpeed, emitSpeed, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_SPEED_SPREAD, SpeedSpread, speedSpread, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_EMIT_ORIENTATION, EmitOrientation, emitOrientation, glm::quat); - ADD_PROPERTY_TO_MAP(PROP_EMIT_DIMENSIONS, EmitDimensions, emitDimensions, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_EMIT_RADIUS_START, EmitRadiusStart, emitRadiusStart, float); - ADD_PROPERTY_TO_MAP(PROP_POLAR_START, EmitPolarStart, polarStart, float); - ADD_PROPERTY_TO_MAP(PROP_POLAR_FINISH, EmitPolarFinish, polarFinish, float); - ADD_PROPERTY_TO_MAP(PROP_AZIMUTH_START, EmitAzimuthStart, azimuthStart, float); - ADD_PROPERTY_TO_MAP(PROP_AZIMUTH_FINISH, EmitAzimuthFinish, azimuthFinish, float); - ADD_PROPERTY_TO_MAP(PROP_EMIT_ACCELERATION, EmitAcceleration, emitAcceleration, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_ACCELERATION_SPREAD, AccelerationSpread, accelerationSpread, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_PARTICLE_RADIUS, ParticleRadius, particleRadius, float); - ADD_PROPERTY_TO_MAP(PROP_RADIUS_SPREAD, RadiusSpread, radiusSpread, float); - ADD_PROPERTY_TO_MAP(PROP_RADIUS_START, RadiusStart, radiusStart, float); - ADD_PROPERTY_TO_MAP(PROP_RADIUS_FINISH, RadiusFinish, radiusFinish, float); - ADD_PROPERTY_TO_MAP(PROP_MARKETPLACE_ID, MarketplaceID, marketplaceID, QString); - ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_COLOR, KeyLightColor, keyLightColor, xColor); - ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_INTENSITY, KeyLightIntensity, keyLightIntensity, float); - ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_AMBIENT_INTENSITY, KeyLightAmbientIntensity, keyLightAmbientIntensity, float); - ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_DIRECTION, KeyLightDirection, keyLightDirection, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_VOXEL_VOLUME_SIZE, VoxelVolumeSize, voxelVolumeSize, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_VOXEL_DATA, VoxelData, voxelData, QByteArray); - ADD_PROPERTY_TO_MAP(PROP_VOXEL_SURFACE_STYLE, VoxelSurfaceStyle, voxelSurfaceStyle, uint16_t); - ADD_PROPERTY_TO_MAP(PROP_NAME, Name, name, QString); - ADD_PROPERTY_TO_MAP(PROP_BACKGROUND_MODE, BackgroundMode, backgroundMode, BackgroundMode); - ADD_PROPERTY_TO_MAP(PROP_SOURCE_URL, SourceUrl, sourceUrl, QString); - ADD_PROPERTY_TO_MAP(PROP_LINE_WIDTH, LineWidth, lineWidth, float); - ADD_PROPERTY_TO_MAP(PROP_LINE_POINTS, LinePoints, linePoints, QVector); - ADD_PROPERTY_TO_MAP(PROP_HREF, Href, href, QString); - ADD_PROPERTY_TO_MAP(PROP_DESCRIPTION, Description, description, QString); - ADD_PROPERTY_TO_MAP(PROP_FACE_CAMERA, FaceCamera, faceCamera, bool); - ADD_PROPERTY_TO_MAP(PROP_ACTION_DATA, ActionData, actionData, QByteArray); - ADD_PROPERTY_TO_MAP(PROP_NORMALS, Normals, normals, QVector); - ADD_PROPERTY_TO_MAP(PROP_STROKE_WIDTHS, StrokeWidths, strokeWidths, QVector); - ADD_PROPERTY_TO_MAP(PROP_X_TEXTURE_URL, XTextureURL, xTextureURL, QString); - ADD_PROPERTY_TO_MAP(PROP_Y_TEXTURE_URL, YTextureURL, yTextureURL, QString); - ADD_PROPERTY_TO_MAP(PROP_Z_TEXTURE_URL, ZTextureURL, zTextureURL, QString); - ADD_PROPERTY_TO_MAP(PROP_X_N_NEIGHBOR_ID, XNNeighborID, xNNeighborID, EntityItemID); - ADD_PROPERTY_TO_MAP(PROP_Y_N_NEIGHBOR_ID, YNNeighborID, yNNeighborID, EntityItemID); - ADD_PROPERTY_TO_MAP(PROP_Z_N_NEIGHBOR_ID, ZNNeighborID, zNNeighborID, EntityItemID); - ADD_PROPERTY_TO_MAP(PROP_X_P_NEIGHBOR_ID, XPNeighborID, xPNeighborID, EntityItemID); - ADD_PROPERTY_TO_MAP(PROP_Y_P_NEIGHBOR_ID, YPNeighborID, yPNeighborID, EntityItemID); - ADD_PROPERTY_TO_MAP(PROP_Z_P_NEIGHBOR_ID, ZPNeighborID, zPNeighborID, EntityItemID); - - ADD_PROPERTY_TO_MAP(PROP_PARENT_ID, ParentID, parentID, QUuid); - ADD_PROPERTY_TO_MAP(PROP_PARENT_JOINT_INDEX, ParentJointIndex, parentJointIndex, uint16_t); - - ADD_PROPERTY_TO_MAP(PROP_LOCAL_POSITION, LocalPosition, localPosition, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_LOCAL_ROTATION, LocalRotation, localRotation, glm::quat); - ADD_PROPERTY_TO_MAP(PROP_LOCAL_VELOCITY, LocalVelocity, localVelocity, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_LOCAL_ANGULAR_VELOCITY, LocalAngularVelocity, localAngularVelocity, glm::vec3); - - ADD_PROPERTY_TO_MAP(PROP_JOINT_ROTATIONS_SET, JointRotationsSet, jointRotationsSet, QVector); - ADD_PROPERTY_TO_MAP(PROP_JOINT_ROTATIONS, JointRotations, jointRotations, QVector); - ADD_PROPERTY_TO_MAP(PROP_JOINT_TRANSLATIONS_SET, JointTranslationsSet, jointTranslationsSet, QVector); - ADD_PROPERTY_TO_MAP(PROP_JOINT_TRANSLATIONS, JointTranslations, jointTranslations, QVector); - - ADD_PROPERTY_TO_MAP(PROP_SHAPE, Shape, shape, QString); - - ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_URL, Animation, animation, URL, url); - ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_FPS, Animation, animation, FPS, fps); - ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_FRAME_INDEX, Animation, animation, CurrentFrame, currentFrame); - ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_PLAYING, Animation, animation, Running, running); - ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_LOOP, Animation, animation, Loop, loop); - ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_FIRST_FRAME, Animation, animation, FirstFrame, firstFrame); - ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_LAST_FRAME, Animation, animation, LastFrame, lastFrame); - ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_HOLD, Animation, animation, Hold, hold); - - ADD_GROUP_PROPERTY_TO_MAP(PROP_SKYBOX_COLOR, Skybox, skybox, Color, color); - ADD_GROUP_PROPERTY_TO_MAP(PROP_SKYBOX_URL, Skybox, skybox, URL, url); - - ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_SUN_MODEL_ENABLED, Stage, stage, SunModelEnabled, sunModelEnabled); - ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_LATITUDE, Stage, stage, Latitude, latitude); - ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_LONGITUDE, Stage, stage, Longitude, longitude); - ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_ALTITUDE, Stage, stage, Altitude, altitude); - ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_DAY, Stage, stage, Day, day); - ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_HOUR, Stage, stage, Hour, hour); - ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_AUTOMATIC_HOURDAY, Stage, stage, AutomaticHourDay, automaticHourDay); - - ADD_PROPERTY_TO_MAP(PROP_FLYING_ALLOWED, FlyingAllowed, flyingAllowed, bool); - ADD_PROPERTY_TO_MAP(PROP_GHOSTING_ALLOWED, GhostingAllowed, ghostingAllowed, bool); - - ADD_PROPERTY_TO_MAP(PROP_DPI, DPI, dpi, uint16_t); - - // FIXME - these are not yet handled - //ADD_PROPERTY_TO_MAP(PROP_CREATED, Created, created, quint64); - - }); } @@ -1064,7 +917,155 @@ QScriptValue EntityItemProperties::entityPropertyFlagsToScriptValue(QScriptEngin return result; } +static QHash _propertyStringsToEnums; + void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue& object, EntityPropertyFlags& flags) { + + static std::once_flag initMap; + + std::call_once(initMap, [](){ + ADD_PROPERTY_TO_MAP(PROP_VISIBLE, Visible, visible, bool); + ADD_PROPERTY_TO_MAP(PROP_POSITION, Position, position, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_DIMENSIONS, Dimensions, dimensions, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_ROTATION, Rotation, rotation, glm::quat); + ADD_PROPERTY_TO_MAP(PROP_DENSITY, Density, density, float); + ADD_PROPERTY_TO_MAP(PROP_VELOCITY, Velocity, velocity, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_GRAVITY, Gravity, gravity, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_ACCELERATION, Acceleration, acceleration, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_DAMPING, Damping, damping, float); + ADD_PROPERTY_TO_MAP(PROP_RESTITUTION, Restitution, restitution, float); + ADD_PROPERTY_TO_MAP(PROP_FRICTION, Friction, friction, float); + ADD_PROPERTY_TO_MAP(PROP_LIFETIME, Lifetime, lifetime, float); + ADD_PROPERTY_TO_MAP(PROP_SCRIPT, Script, script, QString); + ADD_PROPERTY_TO_MAP(PROP_SCRIPT_TIMESTAMP, ScriptTimestamp, scriptTimestamp, quint64); + ADD_PROPERTY_TO_MAP(PROP_SERVER_SCRIPTS, ServerScripts, serverScripts, QString); + ADD_PROPERTY_TO_MAP(PROP_COLLISION_SOUND_URL, CollisionSoundURL, collisionSoundURL, QString); + ADD_PROPERTY_TO_MAP(PROP_COLOR, Color, color, xColor); + ADD_PROPERTY_TO_MAP(PROP_COLOR_SPREAD, ColorSpread, colorSpread, xColor); + ADD_PROPERTY_TO_MAP(PROP_COLOR_START, ColorStart, colorStart, xColor); + ADD_PROPERTY_TO_MAP(PROP_COLOR_FINISH, ColorFinish, colorFinish, xColor); + ADD_PROPERTY_TO_MAP(PROP_ALPHA, Alpha, alpha, float); + ADD_PROPERTY_TO_MAP(PROP_ALPHA_SPREAD, AlphaSpread, alphaSpread, float); + ADD_PROPERTY_TO_MAP(PROP_ALPHA_START, AlphaStart, alphaStart, float); + ADD_PROPERTY_TO_MAP(PROP_ALPHA_FINISH, AlphaFinish, alphaFinish, float); + ADD_PROPERTY_TO_MAP(PROP_EMITTER_SHOULD_TRAIL, EmitterShouldTrail, emitterShouldTrail, bool); + ADD_PROPERTY_TO_MAP(PROP_MODEL_URL, ModelURL, modelURL, QString); + ADD_PROPERTY_TO_MAP(PROP_COMPOUND_SHAPE_URL, CompoundShapeURL, compoundShapeURL, QString); + ADD_PROPERTY_TO_MAP(PROP_REGISTRATION_POINT, RegistrationPoint, registrationPoint, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_ANGULAR_VELOCITY, AngularVelocity, angularVelocity, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_ANGULAR_DAMPING, AngularDamping, angularDamping, float); + ADD_PROPERTY_TO_MAP(PROP_COLLISIONLESS, Collisionless, collisionless, bool); + ADD_PROPERTY_TO_MAP(PROP_DYNAMIC, unused, ignoreForCollisions, unused); // legacy support + ADD_PROPERTY_TO_MAP(PROP_COLLISION_MASK, unused, collisionMask, unused); + ADD_PROPERTY_TO_MAP(PROP_COLLISION_MASK, unused, collidesWith, unused); + ADD_PROPERTY_TO_MAP(PROP_DYNAMIC, unused, collisionsWillMove, unused); // legacy support + ADD_PROPERTY_TO_MAP(PROP_DYNAMIC, unused, dynamic, unused); + ADD_PROPERTY_TO_MAP(PROP_IS_SPOTLIGHT, IsSpotlight, isSpotlight, bool); + ADD_PROPERTY_TO_MAP(PROP_INTENSITY, Intensity, intensity, float); + ADD_PROPERTY_TO_MAP(PROP_FALLOFF_RADIUS, FalloffRadius, falloffRadius, float); + ADD_PROPERTY_TO_MAP(PROP_EXPONENT, Exponent, exponent, float); + ADD_PROPERTY_TO_MAP(PROP_CUTOFF, Cutoff, cutoff, float); + ADD_PROPERTY_TO_MAP(PROP_LOCKED, Locked, locked, bool); + ADD_PROPERTY_TO_MAP(PROP_TEXTURES, Textures, textures, QString); + ADD_PROPERTY_TO_MAP(PROP_USER_DATA, UserData, userData, QString); + ADD_PROPERTY_TO_MAP(PROP_SIMULATION_OWNER, SimulationOwner, simulationOwner, SimulationOwner); + ADD_PROPERTY_TO_MAP(PROP_TEXT, Text, text, QString); + ADD_PROPERTY_TO_MAP(PROP_LINE_HEIGHT, LineHeight, lineHeight, float); + ADD_PROPERTY_TO_MAP(PROP_TEXT_COLOR, TextColor, textColor, xColor); + ADD_PROPERTY_TO_MAP(PROP_BACKGROUND_COLOR, BackgroundColor, backgroundColor, xColor); + ADD_PROPERTY_TO_MAP(PROP_SHAPE_TYPE, ShapeType, shapeType, ShapeType); + ADD_PROPERTY_TO_MAP(PROP_MAX_PARTICLES, MaxParticles, maxParticles, quint32); + ADD_PROPERTY_TO_MAP(PROP_LIFESPAN, Lifespan, lifespan, float); + ADD_PROPERTY_TO_MAP(PROP_EMITTING_PARTICLES, IsEmitting, isEmitting, bool); + ADD_PROPERTY_TO_MAP(PROP_EMIT_RATE, EmitRate, emitRate, float); + ADD_PROPERTY_TO_MAP(PROP_EMIT_SPEED, EmitSpeed, emitSpeed, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_SPEED_SPREAD, SpeedSpread, speedSpread, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_EMIT_ORIENTATION, EmitOrientation, emitOrientation, glm::quat); + ADD_PROPERTY_TO_MAP(PROP_EMIT_DIMENSIONS, EmitDimensions, emitDimensions, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_EMIT_RADIUS_START, EmitRadiusStart, emitRadiusStart, float); + ADD_PROPERTY_TO_MAP(PROP_POLAR_START, EmitPolarStart, polarStart, float); + ADD_PROPERTY_TO_MAP(PROP_POLAR_FINISH, EmitPolarFinish, polarFinish, float); + ADD_PROPERTY_TO_MAP(PROP_AZIMUTH_START, EmitAzimuthStart, azimuthStart, float); + ADD_PROPERTY_TO_MAP(PROP_AZIMUTH_FINISH, EmitAzimuthFinish, azimuthFinish, float); + ADD_PROPERTY_TO_MAP(PROP_EMIT_ACCELERATION, EmitAcceleration, emitAcceleration, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_ACCELERATION_SPREAD, AccelerationSpread, accelerationSpread, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_PARTICLE_RADIUS, ParticleRadius, particleRadius, float); + ADD_PROPERTY_TO_MAP(PROP_RADIUS_SPREAD, RadiusSpread, radiusSpread, float); + ADD_PROPERTY_TO_MAP(PROP_RADIUS_START, RadiusStart, radiusStart, float); + ADD_PROPERTY_TO_MAP(PROP_RADIUS_FINISH, RadiusFinish, radiusFinish, float); + ADD_PROPERTY_TO_MAP(PROP_MARKETPLACE_ID, MarketplaceID, marketplaceID, QString); + ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_COLOR, KeyLightColor, keyLightColor, xColor); + ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_INTENSITY, KeyLightIntensity, keyLightIntensity, float); + ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_AMBIENT_INTENSITY, KeyLightAmbientIntensity, keyLightAmbientIntensity, float); + ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_DIRECTION, KeyLightDirection, keyLightDirection, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_VOXEL_VOLUME_SIZE, VoxelVolumeSize, voxelVolumeSize, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_VOXEL_DATA, VoxelData, voxelData, QByteArray); + ADD_PROPERTY_TO_MAP(PROP_VOXEL_SURFACE_STYLE, VoxelSurfaceStyle, voxelSurfaceStyle, uint16_t); + ADD_PROPERTY_TO_MAP(PROP_NAME, Name, name, QString); + ADD_PROPERTY_TO_MAP(PROP_BACKGROUND_MODE, BackgroundMode, backgroundMode, BackgroundMode); + ADD_PROPERTY_TO_MAP(PROP_SOURCE_URL, SourceUrl, sourceUrl, QString); + ADD_PROPERTY_TO_MAP(PROP_LINE_WIDTH, LineWidth, lineWidth, float); + ADD_PROPERTY_TO_MAP(PROP_LINE_POINTS, LinePoints, linePoints, QVector); + ADD_PROPERTY_TO_MAP(PROP_HREF, Href, href, QString); + ADD_PROPERTY_TO_MAP(PROP_DESCRIPTION, Description, description, QString); + ADD_PROPERTY_TO_MAP(PROP_FACE_CAMERA, FaceCamera, faceCamera, bool); + ADD_PROPERTY_TO_MAP(PROP_ACTION_DATA, ActionData, actionData, QByteArray); + ADD_PROPERTY_TO_MAP(PROP_NORMALS, Normals, normals, QVector); + ADD_PROPERTY_TO_MAP(PROP_STROKE_WIDTHS, StrokeWidths, strokeWidths, QVector); + ADD_PROPERTY_TO_MAP(PROP_X_TEXTURE_URL, XTextureURL, xTextureURL, QString); + ADD_PROPERTY_TO_MAP(PROP_Y_TEXTURE_URL, YTextureURL, yTextureURL, QString); + ADD_PROPERTY_TO_MAP(PROP_Z_TEXTURE_URL, ZTextureURL, zTextureURL, QString); + ADD_PROPERTY_TO_MAP(PROP_X_N_NEIGHBOR_ID, XNNeighborID, xNNeighborID, EntityItemID); + ADD_PROPERTY_TO_MAP(PROP_Y_N_NEIGHBOR_ID, YNNeighborID, yNNeighborID, EntityItemID); + ADD_PROPERTY_TO_MAP(PROP_Z_N_NEIGHBOR_ID, ZNNeighborID, zNNeighborID, EntityItemID); + ADD_PROPERTY_TO_MAP(PROP_X_P_NEIGHBOR_ID, XPNeighborID, xPNeighborID, EntityItemID); + ADD_PROPERTY_TO_MAP(PROP_Y_P_NEIGHBOR_ID, YPNeighborID, yPNeighborID, EntityItemID); + ADD_PROPERTY_TO_MAP(PROP_Z_P_NEIGHBOR_ID, ZPNeighborID, zPNeighborID, EntityItemID); + + ADD_PROPERTY_TO_MAP(PROP_PARENT_ID, ParentID, parentID, QUuid); + ADD_PROPERTY_TO_MAP(PROP_PARENT_JOINT_INDEX, ParentJointIndex, parentJointIndex, uint16_t); + + ADD_PROPERTY_TO_MAP(PROP_LOCAL_POSITION, LocalPosition, localPosition, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_LOCAL_ROTATION, LocalRotation, localRotation, glm::quat); + ADD_PROPERTY_TO_MAP(PROP_LOCAL_VELOCITY, LocalVelocity, localVelocity, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_LOCAL_ANGULAR_VELOCITY, LocalAngularVelocity, localAngularVelocity, glm::vec3); + + ADD_PROPERTY_TO_MAP(PROP_JOINT_ROTATIONS_SET, JointRotationsSet, jointRotationsSet, QVector); + ADD_PROPERTY_TO_MAP(PROP_JOINT_ROTATIONS, JointRotations, jointRotations, QVector); + ADD_PROPERTY_TO_MAP(PROP_JOINT_TRANSLATIONS_SET, JointTranslationsSet, jointTranslationsSet, QVector); + ADD_PROPERTY_TO_MAP(PROP_JOINT_TRANSLATIONS, JointTranslations, jointTranslations, QVector); + + ADD_PROPERTY_TO_MAP(PROP_SHAPE, Shape, shape, QString); + + ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_URL, Animation, animation, URL, url); + ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_FPS, Animation, animation, FPS, fps); + ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_FRAME_INDEX, Animation, animation, CurrentFrame, currentFrame); + ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_PLAYING, Animation, animation, Running, running); + ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_LOOP, Animation, animation, Loop, loop); + ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_FIRST_FRAME, Animation, animation, FirstFrame, firstFrame); + ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_LAST_FRAME, Animation, animation, LastFrame, lastFrame); + ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_HOLD, Animation, animation, Hold, hold); + + ADD_GROUP_PROPERTY_TO_MAP(PROP_SKYBOX_COLOR, Skybox, skybox, Color, color); + ADD_GROUP_PROPERTY_TO_MAP(PROP_SKYBOX_URL, Skybox, skybox, URL, url); + + ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_SUN_MODEL_ENABLED, Stage, stage, SunModelEnabled, sunModelEnabled); + ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_LATITUDE, Stage, stage, Latitude, latitude); + ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_LONGITUDE, Stage, stage, Longitude, longitude); + ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_ALTITUDE, Stage, stage, Altitude, altitude); + ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_DAY, Stage, stage, Day, day); + ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_HOUR, Stage, stage, Hour, hour); + ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_AUTOMATIC_HOURDAY, Stage, stage, AutomaticHourDay, automaticHourDay); + + ADD_PROPERTY_TO_MAP(PROP_FLYING_ALLOWED, FlyingAllowed, flyingAllowed, bool); + ADD_PROPERTY_TO_MAP(PROP_GHOSTING_ALLOWED, GhostingAllowed, ghostingAllowed, bool); + + ADD_PROPERTY_TO_MAP(PROP_DPI, DPI, dpi, uint16_t); + + // FIXME - these are not yet handled + //ADD_PROPERTY_TO_MAP(PROP_CREATED, Created, created, quint64); + + }); if (object.isString()) { // TODO: figure out how to do this without a double lookup in the map From 112b119f170c8c1fb73d45a6b8af5c8ef466c572 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Jan 2017 14:56:08 -0800 Subject: [PATCH 024/114] send entities that just stopped matching filter --- .../src/octree/OctreeSendThread.cpp | 2 +- .../entities/src}/EntityNodeData.h | 8 ++++- libraries/entities/src/EntityTreeElement.cpp | 36 ++++++++++++++++--- libraries/octree/src/Octree.h | 8 ++--- .../octree/src}/OctreeQueryNode.cpp | 3 +- .../octree/src}/OctreeQueryNode.h | 12 +++---- 6 files changed, 51 insertions(+), 18 deletions(-) rename {assignment-client/src/entities => libraries/entities/src}/EntityNodeData.h (64%) rename {assignment-client/src/octree => libraries/octree/src}/OctreeQueryNode.cpp (99%) rename {assignment-client/src/octree => libraries/octree/src}/OctreeQueryNode.h (96%) diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 68938887d7..8fb79a336a 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -434,7 +434,7 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode* nodeData->getLastTimeBagEmpty(), isFullScene, &nodeData->stats, _myServer->getJurisdiction(), &nodeData->extraEncodeData, - nodeData->getJSONParameters()); + nodeData); nodeData->copyCurrentViewFrustum(params.viewFrustum); if (viewFrustumChanged) { nodeData->copyLastKnownViewFrustum(params.lastViewFrustum); diff --git a/assignment-client/src/entities/EntityNodeData.h b/libraries/entities/src/EntityNodeData.h similarity index 64% rename from assignment-client/src/entities/EntityNodeData.h rename to libraries/entities/src/EntityNodeData.h index e1f8a91030..b3a576b1ad 100644 --- a/assignment-client/src/entities/EntityNodeData.h +++ b/libraries/entities/src/EntityNodeData.h @@ -14,7 +14,7 @@ #include -#include "../octree/OctreeQueryNode.h" +#include class EntityNodeData : public OctreeQueryNode { public: @@ -22,9 +22,15 @@ public: quint64 getLastDeletedEntitiesSentAt() const { return _lastDeletedEntitiesSentAt; } void setLastDeletedEntitiesSentAt(quint64 sentAt) { _lastDeletedEntitiesSentAt = sentAt; } + + // these can only be called from the OctreeSendThread for the given Node + void insertEntitySentLastFrame(const QUuid& entityID) { _entitiesSentLastFrame.insert(entityID); } + void removeEntitySentLastFrame(const QUuid& entityID) { _entitiesSentLastFrame.remove(entityID); } + bool sentEntityLastFrame(const QUuid& entityID) { return _entitiesSentLastFrame.contains(entityID); } private: quint64 _lastDeletedEntitiesSentAt { usecTimestampNow() }; + QSet _entitiesSentLastFrame; }; #endif // hifi_EntityNodeData_h diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 67a9265aa1..1f9edb6866 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -16,6 +16,7 @@ #include #include "EntitiesLogging.h" +#include "EntityNodeData.h" #include "EntityItemProperties.h" #include "EntityTree.h" #include "EntityTreeElement.h" @@ -231,7 +232,7 @@ void EntityTreeElement::elementEncodeComplete(EncodeBitstreamParams& params) con } OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData* packetData, - EncodeBitstreamParams& params) const { + EncodeBitstreamParams& params) const { OctreeElement::AppendState appendElementState = OctreeElement::COMPLETED; // assume the best... @@ -291,10 +292,37 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData includeThisEntity = false; } - if (!params.jsonFilters.isEmpty()) { - // if params include JSON filters, check if this entity matches - includeThisEntity = includeThisEntity && entity->matchesJSONFilters(params.jsonFilters); + auto entityNodeData = dynamic_cast(params.nodeData); + + if (entityNodeData) { + // we have an EntityNodeData instance + // so we should assume that means we might have JSON filters to check + auto jsonFilters = entityNodeData->getJSONParameters(); + + if (!jsonFilters.isEmpty()) { + // if params include JSON filters, check if this entity matches + bool entityMatchesFilters = entity->matchesJSONFilters(jsonFilters); + + if (entityMatchesFilters) { + // we should include this entity unless it has already been excluded + includeThisEntity = includeThisEntity && true; + + // make sure this entity is in the set of entities sent last frame + entityNodeData->insertEntitySentLastFrame(entity->getID()); + + } else { + // we might include this entity if it matched in the previous frame + if (entityNodeData->sentEntityLastFrame(entity->getID())) { + includeThisEntity = includeThisEntity && true; + + entityNodeData->removeEntitySentLastFrame(entity->getID()); + } else { + includeThisEntity = false; + } + } + } } + if (hadElementExtraData) { includeThisEntity = includeThisEntity && diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index fa739f83a6..9a132d6046 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -82,7 +82,7 @@ public: OctreeSceneStats* stats; JurisdictionMap* jurisdictionMap; OctreeElementExtraEncodeData* extraEncodeData; - QJsonObject jsonFilters; + NodeData* nodeData; // output hints from the encode process typedef enum { @@ -110,8 +110,8 @@ public: bool forceSendScene = true, OctreeSceneStats* stats = IGNORE_SCENE_STATS, JurisdictionMap* jurisdictionMap = IGNORE_JURISDICTION_MAP, - OctreeElementExtraEncodeData* extraEncodeData = NULL, - QJsonObject jsonFilters = QJsonObject()) : + OctreeElementExtraEncodeData* extraEncodeData = nullptr, + NodeData* nodeData = nullptr) : lastQuerySent(lastQuerySent), maxEncodeLevel(maxEncodeLevel), maxLevelReached(0), @@ -124,7 +124,7 @@ public: stats(stats), jurisdictionMap(jurisdictionMap), extraEncodeData(extraEncodeData), - jsonFilters(jsonFilters), + nodeData(nodeData), stopReason(UNKNOWN) { lastViewFrustum.invalidate(); diff --git a/assignment-client/src/octree/OctreeQueryNode.cpp b/libraries/octree/src/OctreeQueryNode.cpp similarity index 99% rename from assignment-client/src/octree/OctreeQueryNode.cpp rename to libraries/octree/src/OctreeQueryNode.cpp index 6b0536e31d..01d2d85704 100644 --- a/assignment-client/src/octree/OctreeQueryNode.cpp +++ b/libraries/octree/src/OctreeQueryNode.cpp @@ -1,6 +1,6 @@ // // OctreeQueryNode.cpp -// assignment-client/src/octree +// libraries/octree/src // // Created by Stephen Birarda on 3/21/13. // Copyright 2013 High Fidelity, Inc. @@ -18,7 +18,6 @@ #include #include -#include "OctreeSendThread.h" void OctreeQueryNode::nodeKilled() { _isShuttingDown = true; diff --git a/assignment-client/src/octree/OctreeQueryNode.h b/libraries/octree/src/OctreeQueryNode.h similarity index 96% rename from assignment-client/src/octree/OctreeQueryNode.h rename to libraries/octree/src/OctreeQueryNode.h index 96f46cb2fa..021b293804 100644 --- a/assignment-client/src/octree/OctreeQueryNode.h +++ b/libraries/octree/src/OctreeQueryNode.h @@ -1,6 +1,6 @@ // // OctreeQueryNode.h -// assignment-client/src/octree +// libraries/octree/src // // Created by Brad Hefta-Gaub on 12/4/13. // Copyright 2013 High Fidelity, Inc. @@ -15,11 +15,11 @@ #include #include -#include -#include -#include -#include -#include +#include "OctreeConstants.h" +#include "OctreeElementBag.h" +#include "OctreePacketData.h" +#include "OctreeQuery.h" +#include "OctreeSceneStats.h" #include "SentPacketHistory.h" #include From e15bf6bfb450647098a96d949226d1777dc6dcbf Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 18 Jan 2017 15:15:29 -0800 Subject: [PATCH 025/114] Automatically query octree --- assignment-client/src/scripts/EntityScriptServer.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index edb5f6126a..fb5afd5a0d 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -186,6 +186,10 @@ void EntityScriptServer::resetEntitiesScriptEngine() { connect(newEngine.data(), &ScriptEngine::warningMessage, scriptEngines, &ScriptEngines::onWarningMessage); connect(newEngine.data(), &ScriptEngine::infoMessage, scriptEngines, &ScriptEngines::onInfoMessage); + connect(newEngine.data(), &ScriptEngine::update, this, [this] { + _entityViewer.queryOctree(); + }); + newEngine->runInThread(); DependencyManager::get()->setEntitiesScriptEngine(newEngine.data()); From e94cccf08d65f707f2e19ce5a88852ead814f5a0 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 18 Jan 2017 15:57:55 -0800 Subject: [PATCH 026/114] Fix server script preload funcitons --- assignment-client/src/scripts/EntityScriptServer.cpp | 4 ++-- libraries/entities/src/EntityItem.h | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index fb5afd5a0d..fba375aeef 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -243,11 +243,11 @@ void EntityScriptServer::entityServerScriptChanging(const EntityItemID& entityID void EntityScriptServer::checkAndCallPreload(const EntityItemID& entityID, const bool reload) { if (_entityViewer.getTree() && !_shuttingDown) { EntityItemPointer entity = _entityViewer.getTree()->findEntityByEntityItemID(entityID); - if (entity && entity->shouldPreloadScript() && _entitiesScriptEngine) { + if (entity && entity->shouldPreloadServerScript() && _entitiesScriptEngine) { QString scriptUrl = entity->getServerScripts(); scriptUrl = ResourceManager::normalizeURL(scriptUrl); ScriptEngine::loadEntityScript(_entitiesScriptEngine, entityID, scriptUrl, reload); - entity->scriptHasPreloaded(); + entity->serverScriptHasPreloaded(); } } } diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 60afe38662..8ea0df1f1a 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -444,9 +444,8 @@ public: ((_loadedScript != _script) || (_loadedScriptTimestamp != _scriptTimestamp)); } void scriptHasPreloaded() { _loadedScript = _script; _loadedScriptTimestamp = _scriptTimestamp; } - bool shouldPreloadServerScript() const { return !_script.isEmpty() && - ((_loadedScript != _script) || (_loadedScriptTimestamp != _scriptTimestamp)); } - void serverScriptHasPreloaded() { _loadedScript = _script; _loadedScriptTimestamp = _scriptTimestamp; } + bool shouldPreloadServerScript() const { return !_serverScripts.isEmpty() && ((_loadedScript != _script)); } + void serverScriptHasPreloaded() { _loadedScript = _script; } bool getClientOnly() const { return _clientOnly; } void setClientOnly(bool clientOnly) { _clientOnly = clientOnly; } @@ -520,6 +519,7 @@ protected: QString _loadedScript; /// the value of _script when the last preload signal was sent quint64 _scriptTimestamp{ ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP }; /// the script loaded property used for forced reload QString _serverScripts; + QString _loadedServerScripts; /// the value of _scriptTimestamp when the last preload signal was sent // NOTE: on construction we want this to be different from _scriptTimestamp so we intentionally bump it From cbc69fbf9e768fd47cf91d68b0c4051f9cef5165 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 18 Jan 2017 16:37:01 -0800 Subject: [PATCH 027/114] Fix script preload functions --- libraries/entities/src/EntityItem.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 8ea0df1f1a..d4b62e74de 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -444,8 +444,8 @@ public: ((_loadedScript != _script) || (_loadedScriptTimestamp != _scriptTimestamp)); } void scriptHasPreloaded() { _loadedScript = _script; _loadedScriptTimestamp = _scriptTimestamp; } - bool shouldPreloadServerScript() const { return !_serverScripts.isEmpty() && ((_loadedScript != _script)); } - void serverScriptHasPreloaded() { _loadedScript = _script; } + bool shouldPreloadServerScript() const { return !_serverScripts.isEmpty() && ((_loadedServerScripts != _serverScripts)); } + void serverScriptHasPreloaded() { _loadedServerScripts = _serverScripts; } bool getClientOnly() const { return _clientOnly; } void setClientOnly(bool clientOnly) { _clientOnly = clientOnly; } From 6b0b19d36dff8daa9a68a38170d93b221888b2a4 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 18 Jan 2017 17:45:14 -0800 Subject: [PATCH 028/114] Unload all scripts on entity server loss --- assignment-client/src/scripts/EntityScriptServer.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index fba375aeef..f06d1a5b6f 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -253,7 +253,10 @@ void EntityScriptServer::checkAndCallPreload(const EntityItemID& entityID, const } void EntityScriptServer::nodeKilled(SharedNodePointer killedNode) { - + if (killedNode->getType() == NodeType::EntityServer) { + _entitiesScriptEngine->unloadAllEntityScripts(); + resetEntitiesScriptEngine(); + } } void EntityScriptServer::sendStatsPacket() { From ed41412d95bb3e0d81b3093f31161ea994ac0636 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Jan 2017 16:13:03 -0800 Subject: [PATCH 029/114] fix for unpack of OctreeQuery --- assignment-client/src/octree/OctreeSendThread.cpp | 6 +++++- assignment-client/src/scripts/EntityScriptServer.cpp | 1 + libraries/entities/src/EntityTreeElement.cpp | 4 ++-- libraries/octree/src/OctreeQuery.cpp | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 8fb79a336a..05f131f6c8 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -450,7 +450,11 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode* // it seems like it may be a good idea to include the lock time as part of the encode time // are reported to client. Since you can encode without the lock nodeData->stats.encodeStarted(); - + + if (node->getType() == NodeType::EntityScriptServer) { + qDebug() << "Encoding tree bitstream for" << node->getUUID(); + } + bytesWritten = _myServer->getOctree()->encodeTreeBitstream(subTree, &_packetData, nodeData->elementBag, params); quint64 encodeEnd = usecTimestampNow(); diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index f06d1a5b6f..d3aaff60a7 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -224,6 +224,7 @@ void EntityScriptServer::shutdown() { } void EntityScriptServer::addingEntity(const EntityItemID& entityID) { + qDebug() << "adding " << entityID; checkAndCallPreload(entityID); } diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 1f9edb6866..c3c0eafad7 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -279,7 +279,7 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData int numberOfEntitiesOffset = 0; withReadLock([&] { QVector indexesOfEntitiesToInclude; - + // It's possible that our element has been previous completed. In this case we'll simply not include any of our // entities for encoding. This is needed because we encode the element data at the "parent" level, and so we // need to handle the case where our sibling elements need encoding but we don't. @@ -300,6 +300,7 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData auto jsonFilters = entityNodeData->getJSONParameters(); if (!jsonFilters.isEmpty()) { + // if params include JSON filters, check if this entity matches bool entityMatchesFilters = entity->matchesJSONFilters(jsonFilters); @@ -322,7 +323,6 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData } } } - if (hadElementExtraData) { includeThisEntity = includeThisEntity && diff --git a/libraries/octree/src/OctreeQuery.cpp b/libraries/octree/src/OctreeQuery.cpp index 73fe777646..d9decf03e7 100644 --- a/libraries/octree/src/OctreeQuery.cpp +++ b/libraries/octree/src/OctreeQuery.cpp @@ -90,7 +90,7 @@ int OctreeQuery::parseData(ReceivedMessage& message) { // check if this query uses a view frustum memcpy(&_usesFrustum, sourceBuffer, sizeof(_usesFrustum)); - sourceBuffer += _usesFrustum; + sourceBuffer += sizeof(_usesFrustum); if (_usesFrustum) { // unpack camera details From 5fbdc94c66369ffbe29f2b0766dd85f7e44e524b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Jan 2017 16:18:43 -0800 Subject: [PATCH 030/114] pass usesFrustum down to EntityTreeElement --- assignment-client/src/octree/OctreeSendThread.cpp | 1 + libraries/entities/src/EntityTreeElement.cpp | 2 +- libraries/octree/src/Octree.h | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 05f131f6c8..37bfd29db4 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -434,6 +434,7 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode* nodeData->getLastTimeBagEmpty(), isFullScene, &nodeData->stats, _myServer->getJurisdiction(), &nodeData->extraEncodeData, + nodeData->getUsesFrustum(), nodeData); nodeData->copyCurrentViewFrustum(params.viewFrustum); if (viewFrustumChanged) { diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index c3c0eafad7..7ece947e89 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -329,7 +329,7 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData entityTreeElementExtraEncodeData->entities.contains(entity->getEntityItemID()); } - if (includeThisEntity || params.recurseEverything) { + if (params.usesFrustum && (includeThisEntity || params.recurseEverything)) { // we want to use the maximum possible box for this, so that we don't have to worry about the nuance of // simulation changing what's visible. consider the case where the entity contains an angular velocity diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index 9a132d6046..3ccee70871 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -82,6 +82,7 @@ public: OctreeSceneStats* stats; JurisdictionMap* jurisdictionMap; OctreeElementExtraEncodeData* extraEncodeData; + bool usesFrustum; NodeData* nodeData; // output hints from the encode process @@ -111,6 +112,7 @@ public: OctreeSceneStats* stats = IGNORE_SCENE_STATS, JurisdictionMap* jurisdictionMap = IGNORE_JURISDICTION_MAP, OctreeElementExtraEncodeData* extraEncodeData = nullptr, + bool usesFrustum = true, NodeData* nodeData = nullptr) : lastQuerySent(lastQuerySent), maxEncodeLevel(maxEncodeLevel), @@ -124,6 +126,7 @@ public: stats(stats), jurisdictionMap(jurisdictionMap), extraEncodeData(extraEncodeData), + usesFrustum(usesFrustum), nodeData(nodeData), stopReason(UNKNOWN) { From a86be14b8c5a65de76a95c5b4b5dd3efd35dcbe7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Jan 2017 16:20:14 -0800 Subject: [PATCH 031/114] remove debug in OctreeSendThread --- assignment-client/src/octree/OctreeSendThread.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 37bfd29db4..758317dd3b 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -452,10 +452,6 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode* // are reported to client. Since you can encode without the lock nodeData->stats.encodeStarted(); - if (node->getType() == NodeType::EntityScriptServer) { - qDebug() << "Encoding tree bitstream for" << node->getUUID(); - } - bytesWritten = _myServer->getOctree()->encodeTreeBitstream(subTree, &_packetData, nodeData->elementBag, params); quint64 encodeEnd = usecTimestampNow(); From 916a7325bcf774331d9175de87b90180ea078738 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Jan 2017 16:20:34 -0800 Subject: [PATCH 032/114] remove debug in EntityScriptServer --- assignment-client/src/scripts/EntityScriptServer.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index d3aaff60a7..f06d1a5b6f 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -224,7 +224,6 @@ void EntityScriptServer::shutdown() { } void EntityScriptServer::addingEntity(const EntityItemID& entityID) { - qDebug() << "adding " << entityID; checkAndCallPreload(entityID); } From 33cde412b13d9a8f7a5a0f5bc47917165e10d557 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Jan 2017 17:43:57 -0800 Subject: [PATCH 033/114] make getJSONParameters thread-safe --- assignment-client/src/scripts/EntityScriptServer.cpp | 1 + libraries/entities/src/EntityItem.cpp | 2 +- libraries/octree/src/OctreeQuery.cpp | 5 ++++- libraries/octree/src/OctreeQuery.h | 7 +++++-- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index f06d1a5b6f..ff3c0b09c5 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -246,6 +246,7 @@ void EntityScriptServer::checkAndCallPreload(const EntityItemID& entityID, const if (entity && entity->shouldPreloadServerScript() && _entitiesScriptEngine) { QString scriptUrl = entity->getServerScripts(); scriptUrl = ResourceManager::normalizeURL(scriptUrl); + qDebug() << "Loading entity server script" << scriptUrl << "for" << entityID; ScriptEngine::loadEntityScript(_entitiesScriptEngine, entityID, scriptUrl, reload); entity->serverScriptHasPreloaded(); } diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index f9038fd547..0b2e7fd5ca 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -2246,7 +2246,7 @@ bool EntityItem::matchesJSONFilters(const QJsonObject& jsonFilters) const { static const QString SERVER_SCRIPTS_PROPERTY = "serverScripts"; - for (auto& property : jsonFilters.keys()) { + foreach(const auto& property, jsonFilters.keys()) { if (property == SERVER_SCRIPTS_PROPERTY && jsonFilters[property] == EntityQueryFilterSymbol::NonDefault) { // check if this entity has a non-default value for serverScripts if (_serverScripts != ENTITY_ITEM_DEFAULT_SERVER_SCRIPTS) { diff --git a/libraries/octree/src/OctreeQuery.cpp b/libraries/octree/src/OctreeQuery.cpp index d9decf03e7..a639eccaba 100644 --- a/libraries/octree/src/OctreeQuery.cpp +++ b/libraries/octree/src/OctreeQuery.cpp @@ -132,7 +132,10 @@ int OctreeQuery::parseData(ReceivedMessage& message) { sourceBuffer += binaryParametersBytes; // grab the parameter object from the packed binary representation of JSON - _jsonParameters = QJsonDocument::fromBinaryData(binaryJSONParameters).object(); + auto newJsonDocument = QJsonDocument::fromBinaryData(binaryJSONParameters); + + QWriteLocker jsonParameterLocker { &_jsonParametersLock }; + _jsonParameters = newJsonDocument.object(); } return sourceBuffer - startPosition; diff --git a/libraries/octree/src/OctreeQuery.h b/libraries/octree/src/OctreeQuery.h index 79285697a5..058c1dc585 100644 --- a/libraries/octree/src/OctreeQuery.h +++ b/libraries/octree/src/OctreeQuery.h @@ -32,6 +32,7 @@ typedef unsigned long long quint64; #include #include +#include #include @@ -69,8 +70,9 @@ public: void setCameraCenterRadius(float radius) { _cameraCenterRadius = radius; } // getters/setters for JSON filter - QJsonObject getJSONParameters() { return _jsonParameters; } - void setJSONParameters(const QJsonObject& jsonParameters) { _jsonParameters = jsonParameters; } + QJsonObject getJSONParameters() { QReadLocker locker { &_jsonParametersLock }; return _jsonParameters; } + void setJSONParameters(const QJsonObject& jsonParameters) + { QWriteLocker locker { &_jsonParametersLock }; _jsonParameters = jsonParameters; } // related to Octree Sending strategies int getMaxQueryPacketsPerSecond() const { return _maxQueryPPS; } @@ -104,6 +106,7 @@ protected: uint8_t _usesFrustum = true; QJsonObject _jsonParameters; + QReadWriteLock _jsonParametersLock; private: // privatize the copy constructor and assignment operator so they cannot be called From 784b23d05c2210d645d500adb766e9e011e6415a Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Thu, 19 Jan 2017 10:33:04 -0800 Subject: [PATCH 034/114] Partial support for floating-point audio output --- libraries/audio-client/src/AudioClient.cpp | 43 +++++++++++++--- libraries/audio/src/AudioRingBuffer.h | 59 ++++++++++++++-------- 2 files changed, 73 insertions(+), 29 deletions(-) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 1e3dc11338..e2d2dd499b 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -433,8 +433,21 @@ bool adjustedFormatForAudioDevice(const QAudioDeviceInfo& audioDevice, for (int channelCount : (desiredAudioFormat.channelCount() == 1 ? inputChannels : outputChannels)) { for (int sampleRate : sampleRates) { + // int16_t samples adjustedAudioFormat.setChannelCount(channelCount); adjustedAudioFormat.setSampleRate(sampleRate); + adjustedAudioFormat.setSampleSize(16); + adjustedAudioFormat.setSampleType(QAudioFormat::SignedInt); + + if (audioDevice.isFormatSupported(adjustedAudioFormat)) { + return true; + } + + // float samples + adjustedAudioFormat.setChannelCount(channelCount); + adjustedAudioFormat.setSampleRate(sampleRate); + adjustedAudioFormat.setSampleSize(32); + adjustedAudioFormat.setSampleType(QAudioFormat::Float); if (audioDevice.isFormatSupported(adjustedAudioFormat)) { return true; @@ -1545,11 +1558,15 @@ float AudioClient::gainForSource(float distance, float volume) { return gain; } -qint64 AudioClient::AudioOutputIODevice::readData(char * data, qint64 maxSize) { +qint64 AudioClient::AudioOutputIODevice::readData(char* data, qint64 maxSize) { + + // data can be int16_t* or float* + int sampleSize = _audio->_outputFormat.sampleSize() / 8; + bool isFloat = _audio->_outputFormat.sampleType() == QAudioFormat::SampleType::Float; // samples requested from OUTPUT_CHANNEL_COUNT int deviceChannelCount = _audio->_outputFormat.channelCount(); - int samplesRequested = (int)(maxSize / AudioConstants::SAMPLE_SIZE) * OUTPUT_CHANNEL_COUNT / deviceChannelCount; + int samplesRequested = (int)(maxSize / sampleSize) * OUTPUT_CHANNEL_COUNT / deviceChannelCount; int samplesPopped; int bytesWritten; @@ -1559,14 +1576,24 @@ qint64 AudioClient::AudioOutputIODevice::readData(char * data, qint64 maxSize) { AudioRingBuffer::ConstIterator lastPopOutput = _receivedAudioStream.getLastPopOutput(); // if required, upmix or downmix to deviceChannelCount - if (deviceChannelCount == OUTPUT_CHANNEL_COUNT) { - lastPopOutput.readSamples((int16_t*)data, samplesPopped); - } else if (deviceChannelCount > OUTPUT_CHANNEL_COUNT) { - lastPopOutput.readSamplesWithUpmix((int16_t*)data, samplesPopped, deviceChannelCount - OUTPUT_CHANNEL_COUNT); + if (isFloat) { + if (deviceChannelCount == OUTPUT_CHANNEL_COUNT) { + lastPopOutput.readSamples((float*)data, samplesPopped); + } else if (deviceChannelCount > OUTPUT_CHANNEL_COUNT) { + lastPopOutput.readSamplesWithUpmix((float*)data, samplesPopped, deviceChannelCount - OUTPUT_CHANNEL_COUNT); + } else { + lastPopOutput.readSamplesWithDownmix((float*)data, samplesPopped); + } } else { - lastPopOutput.readSamplesWithDownmix((int16_t*)data, samplesPopped); + if (deviceChannelCount == OUTPUT_CHANNEL_COUNT) { + lastPopOutput.readSamples((int16_t*)data, samplesPopped); + } else if (deviceChannelCount > OUTPUT_CHANNEL_COUNT) { + lastPopOutput.readSamplesWithUpmix((int16_t*)data, samplesPopped, deviceChannelCount - OUTPUT_CHANNEL_COUNT); + } else { + lastPopOutput.readSamplesWithDownmix((int16_t*)data, samplesPopped); + } } - bytesWritten = (samplesPopped * AudioConstants::SAMPLE_SIZE) * deviceChannelCount / OUTPUT_CHANNEL_COUNT; + bytesWritten = (samplesPopped * sampleSize) * deviceChannelCount / OUTPUT_CHANNEL_COUNT; } else { // nothing on network, don't grab anything from injectors, and just return 0s // this will flood the log: qCDebug(audioclient, "empty/partial network buffer"); diff --git a/libraries/audio/src/AudioRingBuffer.h b/libraries/audio/src/AudioRingBuffer.h index 29e7a9e998..38ca319156 100644 --- a/libraries/audio/src/AudioRingBuffer.h +++ b/libraries/audio/src/AudioRingBuffer.h @@ -103,10 +103,11 @@ public: ConstIterator operator+(int i); ConstIterator operator-(int i); - void readSamples(int16_t* dest, int numSamples); - void readSamplesWithFade(int16_t* dest, int numSamples, float fade); - void readSamplesWithUpmix(int16_t* dest, int numSamples, int numExtraChannels); - void readSamplesWithDownmix(int16_t* dest, int numSamples); + // dest can be int16_t* or float* + template void readSamples(T* dest, int numSamples); + template void readSamplesWithFade(T* dest, int numSamples, float fade); + template void readSamplesWithUpmix(T* dest, int numSamples, int numExtraChannels); + template void readSamplesWithDownmix(T* dest, int numSamples); private: int16_t* atShiftedBy(int i); @@ -203,6 +204,28 @@ inline int16_t* AudioRingBuffer::ConstIterator::atShiftedBy(int i) { return _bufferFirst + i; } +inline AudioRingBuffer::ConstIterator AudioRingBuffer::nextOutput() const { + return ConstIterator(_buffer, _bufferLength, _nextOutput); +} + +inline AudioRingBuffer::ConstIterator AudioRingBuffer::lastFrameWritten() const { + return ConstIterator(_buffer, _bufferLength, _endOfLastWrite) - _numFrameSamples; +} + +// +// dest can be int16_t* or float* +// +template +inline void AudioRingBuffer::ConstIterator::readSamples(T* dest, int numSamples) { + int16_t* at = _at; + for (int i = 0; i < numSamples; i++) { + *dest++ = (T)*at; + at = (at == _bufferLast) ? _bufferFirst : at + 1; + } +} + +// fast path for int16_t* +template<> inline void AudioRingBuffer::ConstIterator::readSamples(int16_t* dest, int numSamples) { auto samplesToEnd = _bufferLast - _at + 1; @@ -218,16 +241,17 @@ inline void AudioRingBuffer::ConstIterator::readSamples(int16_t* dest, int numSa } } -inline void AudioRingBuffer::ConstIterator::readSamplesWithFade(int16_t* dest, int numSamples, float fade) { +template +inline void AudioRingBuffer::ConstIterator::readSamplesWithFade(T* dest, int numSamples, float fade) { int16_t* at = _at; for (int i = 0; i < numSamples; i++) { - *dest = (float)*at * fade; - ++dest; + *dest++ = (T)(*at * fade); at = (at == _bufferLast) ? _bufferFirst : at + 1; } } -inline void AudioRingBuffer::ConstIterator::readSamplesWithUpmix(int16_t* dest, int numSamples, int numExtraChannels) { +template +inline void AudioRingBuffer::ConstIterator::readSamplesWithUpmix(T* dest, int numSamples, int numExtraChannels) { int16_t* at = _at; for (int i = 0; i < numSamples/2; i++) { @@ -238,15 +262,16 @@ inline void AudioRingBuffer::ConstIterator::readSamplesWithUpmix(int16_t* dest, at = (at == _bufferLast) ? _bufferFirst : at + 1; // write 2 + N samples - *dest++ = left; - *dest++ = right; + *dest++ = (T)left; + *dest++ = (T)right; for (int n = 0; n < numExtraChannels; n++) { - *dest++ = 0; + *dest++ = (T)0; } } } -inline void AudioRingBuffer::ConstIterator::readSamplesWithDownmix(int16_t* dest, int numSamples) { +template +inline void AudioRingBuffer::ConstIterator::readSamplesWithDownmix(T* dest, int numSamples) { int16_t* at = _at; for (int i = 0; i < numSamples/2; i++) { @@ -257,16 +282,8 @@ inline void AudioRingBuffer::ConstIterator::readSamplesWithDownmix(int16_t* dest at = (at == _bufferLast) ? _bufferFirst : at + 1; // write 1 sample - *dest++ = (int16_t)((left + right) / 2); + *dest++ = (T)((left + right) / 2); } } -inline AudioRingBuffer::ConstIterator AudioRingBuffer::nextOutput() const { - return ConstIterator(_buffer, _bufferLength, _nextOutput); -} - -inline AudioRingBuffer::ConstIterator AudioRingBuffer::lastFrameWritten() const { - return ConstIterator(_buffer, _bufferLength, _endOfLastWrite) - _numFrameSamples; -} - #endif // hifi_AudioRingBuffer_h From 746327dc1142f47fc2f6f2de64ae44e4b83c1a10 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 19 Jan 2017 10:43:36 -0800 Subject: [PATCH 035/114] whitespace cleanup in OST --- assignment-client/src/octree/OctreeSendThread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 758317dd3b..fc853820a3 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -451,7 +451,7 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode* // it seems like it may be a good idea to include the lock time as part of the encode time // are reported to client. Since you can encode without the lock nodeData->stats.encodeStarted(); - + bytesWritten = _myServer->getOctree()->encodeTreeBitstream(subTree, &_packetData, nodeData->elementBag, params); quint64 encodeEnd = usecTimestampNow(); From cbb55a06a09664b8c8ae688fabad7aac6034f513 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 19 Jan 2017 13:25:11 -0800 Subject: [PATCH 036/114] Update ScriptEngine to store full running status off entity scripts --- .../src/scripts/EntityScriptServer.cpp | 24 +++++--- libraries/script-engine/src/ScriptEngine.cpp | 51 +++++++++++++--- libraries/script-engine/src/ScriptEngine.h | 60 +++++++++++-------- 3 files changed, 93 insertions(+), 42 deletions(-) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index 5b638f6671..388e04437c 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -11,8 +11,11 @@ #include "EntityScriptServer.h" +#include "EntityScriptUtils.h" + #include #include +#include #include #include #include @@ -23,8 +26,6 @@ #include #include -#include "../entities/AssignmentParentFinder.h" - const size_t UUID_LENGTH_BYTES = 16; int EntityScriptServer::_entitiesScriptEngineCount = 0; @@ -75,16 +76,21 @@ void EntityScriptServer::handleEntityScriptGetStatusPacket(QSharedPointerreadPrimitive(&messageID); auto entityID = QUuid::fromRfc4122(message->read(UUID_LENGTH_BYTES)); - - // TODO(Huffman) Get Status - qDebug() << "Getting script status of: " << entityID; - auto replyPacket = NLPacket::create(PacketType::EntityScriptGetStatusReply, -1, true); - replyPacket->writePrimitive(messageID); - replyPacket->writeString("running"); + auto replyPacketList = NLPacketList::create(PacketType::EntityScriptGetStatusReply, QByteArray(), true, true); + replyPacketList->writePrimitive(messageID); + + EntityScriptDetails details; + if (_entitiesScriptEngine->getEntityScriptDetails(entityID, details)) { + replyPacketList->writePrimitive(true); + replyPacketList->writePrimitive(details.status); + replyPacketList->writeString(details.errorInfo); + } else { + replyPacketList->writePrimitive(false); + } auto nodeList = DependencyManager::get(); - nodeList->sendPacket(std::move(replyPacket), *senderNode); + nodeList->sendPacketList(std::move(replyPacketList), *senderNode); } void EntityScriptServer::run() { diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 2c4512a000..4f6796a2a5 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -1374,6 +1374,15 @@ void ScriptEngine::forwardHandlerCall(const EntityItemID& entityID, const QStrin } } +bool ScriptEngine::getEntityScriptDetails(const EntityItemID& entityID, EntityScriptDetails &details) const { + auto it = _entityScripts.constFind(entityID); + if (it == _entityScripts.constEnd()) { + return false; + } + details = it.value(); + return true; +} + // since all of these operations can be asynch we will always do the actual work in the response handler // for the download void ScriptEngine::loadEntityScript(QWeakPointer theEngine, const EntityItemID& entityID, const QString& entityScript, bool forceRedownload) { @@ -1421,11 +1430,24 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co bool isFileUrl = isURL && scriptOrURL.startsWith("file://"); auto fileName = isURL ? scriptOrURL : "EmbeddedEntityScript"; + EntityScriptDetails newDetails; + newDetails.scriptText = isURL ? contents : scriptOrURL; + + if (!success) { + newDetails.status = ERROR_LOADING_SCRIPT; + newDetails.errorInfo = "Failed to load script"; + _entityScripts[entityID] = newDetails; + return; + } + QScriptProgram program(contents, fileName); if (!hasCorrectSyntax(program, this)) { if (!isFileUrl) { scriptCache->addScriptToBadScriptList(scriptOrURL); } + newDetails.status = ERROR_RUNNING_SCRIPT; + newDetails.errorInfo = "Bad syntax"; + _entityScripts[entityID] = newDetails; return; // done processing script } @@ -1451,6 +1473,10 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co testConstructor = sandbox.evaluate(program); } if (hadUncaughtExceptions(sandbox, program.fileName(), this)) { + newDetails.status = ERROR_RUNNING_SCRIPT; + newDetails.errorInfo = "Exception"; + _entityScripts[entityID] = newDetails; + return; } @@ -1473,6 +1499,10 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co scriptCache->addScriptToBadScriptList(scriptOrURL); } + newDetails.status = ERROR_RUNNING_SCRIPT; + newDetails.errorInfo = "Could not find constructor"; + _entityScripts[entityID] = newDetails; + return; // done processing script } @@ -1489,8 +1519,11 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co }; doWithEnvironment(entityID, sandboxURL, initialization); - EntityScriptDetails newDetails = { scriptOrURL, entityScriptObject, lastModified, sandboxURL }; + newDetails.scriptObject = entityScriptObject; + newDetails.lastModified = lastModified; + newDetails.definingSandboxURL = sandboxURL; _entityScripts[entityID] = newDetails; + if (isURL) { setParentURL(""); } @@ -1516,7 +1549,9 @@ void ScriptEngine::unloadEntityScript(const EntityItemID& entityID) { #endif if (_entityScripts.contains(entityID)) { - callEntityScriptMethod(entityID, "unload"); + if (_entityScripts[entityID].status == RUNNING) { + callEntityScriptMethod(entityID, "unload"); + } _entityScripts.remove(entityID); stopAllTimersForEntityScript(entityID); } @@ -1535,7 +1570,9 @@ void ScriptEngine::unloadAllEntityScripts() { qCDebug(scriptengine) << "ScriptEngine::unloadAllEntityScripts() called on correct thread [" << thread() << "]"; #endif foreach(const EntityItemID& entityID, _entityScripts.keys()) { - callEntityScriptMethod(entityID, "unload"); + if (_entityScripts[entityID].status == RUNNING) { + callEntityScriptMethod(entityID, "unload"); + } } _entityScripts.clear(); @@ -1574,7 +1611,7 @@ void ScriptEngine::refreshFileScript(const EntityItemID& entityID) { QString scriptContents = QTextStream(&file).readAll(); this->unloadEntityScript(entityID); this->entityScriptContentAvailable(entityID, details.scriptText, scriptContents, true, true); - if (!_entityScripts.contains(entityID)) { + if (!_entityScripts.contains(entityID) || _entityScripts[entityID].status != RUNNING) { scriptWarningMessage("Reload script " + details.scriptText + " failed"); } else { details = _entityScripts[entityID]; @@ -1633,7 +1670,7 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS #endif refreshFileScript(entityID); - if (_entityScripts.contains(entityID)) { + if (_entityScripts.contains(entityID) && _entityScripts[entityID].status == RUNNING) { EntityScriptDetails details = _entityScripts[entityID]; QScriptValue entityScript = details.scriptObject; // previously loaded if (entityScript.property(methodName).isFunction()) { @@ -1665,7 +1702,7 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS #endif refreshFileScript(entityID); - if (_entityScripts.contains(entityID)) { + if (_entityScripts.contains(entityID) && _entityScripts[entityID].status == RUNNING) { EntityScriptDetails details = _entityScripts[entityID]; QScriptValue entityScript = details.scriptObject; // previously loaded if (entityScript.property(methodName).isFunction()) { @@ -1698,7 +1735,7 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS #endif refreshFileScript(entityID); - if (_entityScripts.contains(entityID)) { + if (_entityScripts.contains(entityID) && _entityScripts[entityID].status == RUNNING) { EntityScriptDetails details = _entityScripts[entityID]; QScriptValue entityScript = details.scriptObject; // previously loaded if (entityScript.property(methodName).isFunction()) { diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index d9a1249b1c..e266ff3bc9 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -29,6 +29,7 @@ #include #include #include +#include #include "PointerEvent.h" #include "ArrayBufferClass.h" @@ -58,10 +59,15 @@ typedef QHash RegisteredEventHandlers; class EntityScriptDetails { public: - QString scriptText; - QScriptValue scriptObject; - int64_t lastModified; - QUrl definingSandboxURL; + EntityScriptStatus status { RUNNING }; + + // If status indicates an error, this contains a human-readable string giving more information about the error. + QString errorInfo { "" }; + + QString scriptText { "" }; + QScriptValue scriptObject { QScriptValue() }; + int64_t lastModified { 0 }; + QUrl definingSandboxURL { QUrl() }; }; class ScriptEngine : public QScriptEngine, public ScriptUser, public EntitiesScriptEngineProvider { @@ -178,6 +184,8 @@ public: void scriptWarningMessage(const QString& message); void scriptInfoMessage(const QString& message); + bool getEntityScriptDetails(const EntityItemID& entityID, EntityScriptDetails &details) const; + public slots: void callAnimationStateHandler(QScriptValue callback, AnimVariantMap parameters, QStringList names, bool useNames, AnimVariantResultHandler resultHandler); void updateMemoryCost(const qint64&); @@ -200,6 +208,28 @@ signals: void doneRunning(); protected: + void init(); + + bool evaluatePending() const { return _evaluatesPending > 0; } + void timerFired(); + void stopAllTimers(); + void stopAllTimersForEntityScript(const EntityItemID& entityID); + void refreshFileScript(const EntityItemID& entityID); + + void setParentURL(const QString& parentURL) { _parentURL = parentURL; } + + QObject* setupTimerWithInterval(const QScriptValue& function, int intervalMS, bool isSingleShot); + void stopTimer(QTimer* timer); + + QHash _registeredHandlers; + void forwardHandlerCall(const EntityItemID& entityID, const QString& eventName, QScriptValueList eventHanderArgs); + Q_INVOKABLE void entityScriptContentAvailable(const EntityItemID& entityID, const QString& scriptOrURL, const QString& contents, bool isURL, bool success); + + EntityItemID currentEntityIdentifier {}; // Contains the defining entity script entity id during execution, if any. Empty for interface script execution. + QUrl currentSandboxURL {}; // The toplevel url string for the entity script that loaded the code being executed, else empty. + void doWithEnvironment(const EntityItemID& entityID, const QUrl& sandboxURL, std::function operation); + void callWithEnvironment(const EntityItemID& entityID, const QUrl& sandboxURL, QScriptValue function, QScriptValue thisObject, QScriptValueList args); + QString _scriptContents; QString _parentURL; std::atomic _isFinished { false }; @@ -215,19 +245,6 @@ protected: bool _debuggable { false }; qint64 _lastUpdate; - void init(); - - bool evaluatePending() const { return _evaluatesPending > 0; } - void timerFired(); - void stopAllTimers(); - void stopAllTimersForEntityScript(const EntityItemID& entityID); - void refreshFileScript(const EntityItemID& entityID); - - void setParentURL(const QString& parentURL) { _parentURL = parentURL; } - - QObject* setupTimerWithInterval(const QScriptValue& function, int intervalMS, bool isSingleShot); - void stopTimer(QTimer* timer); - QString _fileNameString; Quat _quatLibrary; Vec3 _vec3Library; @@ -240,15 +257,6 @@ protected: AssetScriptingInterface _assetScriptingInterface{ this }; - QHash _registeredHandlers; - void forwardHandlerCall(const EntityItemID& entityID, const QString& eventName, QScriptValueList eventHanderArgs); - Q_INVOKABLE void entityScriptContentAvailable(const EntityItemID& entityID, const QString& scriptOrURL, const QString& contents, bool isURL, bool success); - - EntityItemID currentEntityIdentifier {}; // Contains the defining entity script entity id during execution, if any. Empty for interface script execution. - QUrl currentSandboxURL {}; // The toplevel url string for the entity script that loaded the code being executed, else empty. - void doWithEnvironment(const EntityItemID& entityID, const QUrl& sandboxURL, std::function operation); - void callWithEnvironment(const EntityItemID& entityID, const QUrl& sandboxURL, QScriptValue function, QScriptValue thisObject, QScriptValueList args); - std::function _emitScriptUpdates{ [](){ return true; } }; std::recursive_mutex _lock; From fa2893346484806af0c4594661901c30b6ce7d4a Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 19 Jan 2017 13:26:24 -0800 Subject: [PATCH 037/114] Update EntityScriptClient to receive more status information --- .../networking/src/EntityScriptClient.cpp | 28 +++++++++++++------ libraries/networking/src/EntityScriptClient.h | 10 +++++-- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/libraries/networking/src/EntityScriptClient.cpp b/libraries/networking/src/EntityScriptClient.cpp index 2d4b493f11..b844cf4cf3 100644 --- a/libraries/networking/src/EntityScriptClient.cpp +++ b/libraries/networking/src/EntityScriptClient.cpp @@ -1,6 +1,7 @@ #include "EntityScriptClient.h" #include "NodeList.h" #include "NetworkLogging.h" +#include "EntityScriptUtils.h" #include @@ -15,9 +16,12 @@ GetScriptStatusRequest::~GetScriptStatusRequest() { void GetScriptStatusRequest::start() { auto client = DependencyManager::get(); - qDebug() << "Sending script status request"; - client->getEntityServerScriptStatus(_entityID, [this](bool responseReceived) { - qDebug() << "Received script status request"; + client->getEntityServerScriptStatus(_entityID, [this](bool responseReceived, bool isRunning, EntityScriptStatus status, QString errorInfo) { + this->responseReceived = responseReceived; + this->isRunning = isRunning; + this->status = status; + this->errorInfo = errorInfo; + emit finished(this); }); } @@ -84,7 +88,7 @@ MessageID EntityScriptClient::getEntityServerScriptStatus(QUuid entityID, GetScr } } - callback(false); + callback(false, false, ERROR_LOADING_SCRIPT, ""); return INVALID_MESSAGE_ID; } @@ -92,9 +96,17 @@ void EntityScriptClient::handleGetScriptStatusReply(QSharedPointerreadPrimitive(&messageID); + bool isKnown { false }; + EntityScriptStatus status = ERROR_LOADING_SCRIPT; + QString errorInfo { "" }; - auto status = message->readString(); + message->readPrimitive(&messageID); + message->readPrimitive(&isKnown); + + if (isKnown) { + message->readPrimitive(&status); + errorInfo = message->readString(); + } // Check if we have any pending requests for this node auto messageMapIt = _pendingEntityScriptStatusRequests.find(senderNode); @@ -107,7 +119,7 @@ void EntityScriptClient::handleGetScriptStatusReply(QSharedPointersecond; - callback(true); + callback(true, isKnown, status, errorInfo); messageCallbackMap.erase(requestIt); } @@ -145,7 +157,7 @@ void EntityScriptClient::forceFailureOfPendingRequests(SharedNodePointer node) { auto messageMapIt = _pendingEntityScriptStatusRequests.find(node); if (messageMapIt != _pendingEntityScriptStatusRequests.end()) { for (const auto& value : messageMapIt->second) { - value.second(false); + value.second(false, false, ERROR_LOADING_SCRIPT, ""); } messageMapIt->second.clear(); } diff --git a/libraries/networking/src/EntityScriptClient.h b/libraries/networking/src/EntityScriptClient.h index 795ed3e530..c75f930f96 100644 --- a/libraries/networking/src/EntityScriptClient.h +++ b/libraries/networking/src/EntityScriptClient.h @@ -15,14 +15,14 @@ #include "LimitedNodeList.h" #include "ReceivedMessage.h" #include "AssetUtils.h" +#include "EntityScriptUtils.h" #include -#include #include using MessageID = uint32_t; -using GetScriptStatusCallback = std::function; +using GetScriptStatusCallback = std::function; class GetScriptStatusRequest : public QObject { Q_OBJECT @@ -32,13 +32,17 @@ public: Q_INVOKABLE void start(); + bool responseReceived; + bool isRunning; + EntityScriptStatus status; + QString errorInfo; + signals: void finished(GetScriptStatusRequest* request); private: QUuid _entityID; MessageID _messageID; - QString status; }; class EntityScriptClient : public QObject, public Dependency { From d45f5ade97ababe01842ebb5d1efc12633f2fadf Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 19 Jan 2017 13:26:48 -0800 Subject: [PATCH 038/114] Update Entities.getServerScriptStatus to return more information --- .../entities/src/EntityScriptingInterface.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index bba9347cff..ea02a2d5fa 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -680,7 +680,22 @@ bool EntityScriptingInterface::getServerScriptStatus(QUuid entityID, QScriptValu auto client = DependencyManager::get(); auto request = client->createScriptStatusRequest(entityID); connect(request, &GetScriptStatusRequest::finished, callback.engine(), [callback](GetScriptStatusRequest* request) mutable { - QScriptValueList args { true }; + QString statusString; + switch (request->status) { + case RUNNING: + statusString = "running"; + break; + case ERROR_LOADING_SCRIPT: + statusString = "error_loading_script"; + break; + case ERROR_RUNNING_SCRIPT: + statusString = "error_running_script"; + break; + default: + statusString = ""; + break; + } + QScriptValueList args { request->responseReceived, request->isRunning, statusString, request->errorInfo }; callback.call(QScriptValue(), args); request->deleteLater(); }); From c015ac1bd5ae6ccd559927688ae7ec6b44dc4c9b Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 19 Jan 2017 13:27:09 -0800 Subject: [PATCH 039/114] Add display of server script status to edit.js --- scripts/system/edit.js | 69 ++++++++++++++++++++++ scripts/system/html/entityProperties.html | 9 ++- scripts/system/html/js/entityProperties.js | 25 +++++++- 3 files changed, 101 insertions(+), 2 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 3e97c54c43..50bf22a565 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -1388,6 +1388,37 @@ function pushCommandForSelections(createdEntityData, deletedEntityData) { var ENTITY_PROPERTIES_URL = Script.resolvePath('html/entityProperties.html'); +var ServerScriptStatusMonitor = function(entityID, statusCallback) { + var self = this; + + self.entityID = entityID; + self.active = true; + self.sendRequestTimerID = null; + + var onStatusReceived = function(success, isRunning, status, errorInfo) { + print("Got script status:", success, isRunning, status, errorInfo); + if (self.active) { + print("Requesting status of script"); + statusCallback({ + statusRetrieved: success, + isRunning: isRunning, + status: status, + errorInfo: errorInfo + }); + self.sendRequestTimerID = Script.setTimeout(function() { + if (self.active) { + Entities.getServerScriptStatus(entityID, onStatusReceived); + } + }, 1000); + }; + }; + self.stop = function() { + self.active = false; + } + + Entities.getServerScriptStatus(entityID, onStatusReceived); +}; + var PropertiesTool = function (opts) { var that = {}; @@ -1399,6 +1430,11 @@ var PropertiesTool = function (opts) { var visible = false; + // This keeps track of the last entity ID that was selected. If multiple entities + // are selected or if no entity is selected this will be `null`. + var currentSelectedEntityID = null; + var statusMonitor = null; + webView.setVisible(visible); that.setVisible = function (newVisible) { @@ -1406,10 +1442,43 @@ var PropertiesTool = function (opts) { webView.setVisible(visible); }; + function updateScriptStatus(info) { + print("Got status: ", info); + info.type = "server_script_status"; + webView.emitScriptEvent(JSON.stringify(info)); + }; + + function resetScriptStatus() { + updateScriptStatus({ + statusRetrieved: false, + isRunning: false, + status: "", + errorInfo: "" + }); + } + selectionManager.addEventListener(function () { var data = { type: 'update' }; + + resetScriptStatus(); + + if (selectionManager.selections.length !== 1) { + if (statusMonitor !== null) { + statusMonitor.stop(); + statusMonitor = null; + } + currentSelectedEntityID = null; + } else if (currentSelectedEntityID != selectionManager.selections[0]) { + if (statusMonitor !== null) { + statusMonitor.stop(); + } + var entityID = selectionManager.selections[0]; + currentSelectedEntityID = entityID; + statusMonitor = new ServerScriptStatusMonitor(entityID, updateScriptStatus); + } + var selections = []; for (var i = 0; i < selectionManager.selections.length; i++) { var entity = {}; diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index 07a1b300d1..2908ae095e 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -319,10 +319,17 @@
- +
+
+ + +
+
+ +
M
diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index ebd1e67677..286ccf5a38 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -593,6 +593,8 @@ function loaded() { var elReloadScriptsButton = document.getElementById("reload-script-button"); var elServerScripts = document.getElementById("property-server-scripts"); var elReloadServerScriptsButton = document.getElementById("reload-server-scripts-button"); + var elServerScriptStatus = document.getElementById("server-script-status"); + var elServerScriptError = document.getElementById("server-script-error"); var elUserData = document.getElementById("property-user-data"); var elClearUserData = document.getElementById("userdata-clear"); var elSaveUserData = document.getElementById("userdata-save"); @@ -710,7 +712,28 @@ function loaded() { var properties; EventBridge.scriptEventReceived.connect(function(data) { data = JSON.parse(data); - if (data.type == "update") { + if (data.type == "server_script_status") { + if (!data.statusRetrieved) { + elServerScriptStatus.innerHTML = "Failed to retrieve status"; + elServerScriptError.style.display = "none"; + } else if (data.isRunning) { + if (data.status == "running") { + elServerScriptStatus.innerHTML = "Running"; + elServerScriptError.style.display = "none"; + } else if (data.status == "error_loading_script") { + elServerScriptStatus.innerHTML = "Error loading script"; + elServerScriptError.style.display = "block"; + } else if (data.status == "error_running_script") { + elServerScriptStatus.innerHTML = "Error running script"; + elServerScriptError.style.display = "block"; + } + //elServerScriptError.innerHTML = JSON.stringify(data) + "\n" + data.errorInfo;; + elServerScriptError.innerHTML = data.errorInfo;; + } else { + elServerScriptStatus.innerHTML = "Not running"; + elServerScriptError.style.display = "none"; + } + } else if (data.type == "update") { if (data.selections.length == 0) { if (editor !== null && lastEntityID !== null) { From 7fc946f5984ed0b0103da1f9cfcd5ac4faccb582 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 19 Jan 2017 13:31:24 -0800 Subject: [PATCH 040/114] Fix duplicate UUID length constant --- assignment-client/src/scripts/EntityScriptServer.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index 388e04437c..5e5f426233 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -24,10 +24,9 @@ #include #include #include +#include #include -const size_t UUID_LENGTH_BYTES = 16; - int EntityScriptServer::_entitiesScriptEngineCount = 0; EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : ThreadedAssignment(message) { @@ -63,7 +62,7 @@ EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : ThreadedAssig static const QString ENTITY_SCRIPT_SERVER_LOGGING_NAME = "entity-script-server"; void EntityScriptServer::handleReloadEntityServerScriptPacket(QSharedPointer message, SharedNodePointer senderNode) { - auto entityID = QUuid::fromRfc4122(message->read(UUID_LENGTH_BYTES)); + auto entityID = QUuid::fromRfc4122(message->read(NUM_BYTES_RFC4122_UUID)); if (_entityViewer.getTree() && !_shuttingDown) { qDebug() << "Reloading: " << entityID; From 3ac44e3a1cda8f28152303eefc7c126b7f12d65e Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 19 Jan 2017 14:34:44 -0800 Subject: [PATCH 041/114] Add guard against unpermitted requests to the entity script server --- .../src/scripts/EntityScriptServer.cpp | 46 ++++++++++--------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index 5e5f426233..e251dd9841 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -62,34 +62,38 @@ EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : ThreadedAssig static const QString ENTITY_SCRIPT_SERVER_LOGGING_NAME = "entity-script-server"; void EntityScriptServer::handleReloadEntityServerScriptPacket(QSharedPointer message, SharedNodePointer senderNode) { - auto entityID = QUuid::fromRfc4122(message->read(NUM_BYTES_RFC4122_UUID)); + if (senderNode->getCanRez() || senderNode->getCanRezTmp()) { + auto entityID = QUuid::fromRfc4122(message->read(NUM_BYTES_RFC4122_UUID)); - if (_entityViewer.getTree() && !_shuttingDown) { - qDebug() << "Reloading: " << entityID; - _entitiesScriptEngine->unloadEntityScript(entityID); - checkAndCallPreload(entityID, true); + if (_entityViewer.getTree() && !_shuttingDown) { + qDebug() << "Reloading: " << entityID; + _entitiesScriptEngine->unloadEntityScript(entityID); + checkAndCallPreload(entityID, true); + } } } void EntityScriptServer::handleEntityScriptGetStatusPacket(QSharedPointer message, SharedNodePointer senderNode) { - MessageID messageID; - message->readPrimitive(&messageID); - auto entityID = QUuid::fromRfc4122(message->read(UUID_LENGTH_BYTES)); - - auto replyPacketList = NLPacketList::create(PacketType::EntityScriptGetStatusReply, QByteArray(), true, true); - replyPacketList->writePrimitive(messageID); + if (senderNode->getCanRez() || senderNode->getCanRezTmp()) { + MessageID messageID; + message->readPrimitive(&messageID); + auto entityID = QUuid::fromRfc4122(message->read(NUM_BYTES_RFC4122_UUID)); - EntityScriptDetails details; - if (_entitiesScriptEngine->getEntityScriptDetails(entityID, details)) { - replyPacketList->writePrimitive(true); - replyPacketList->writePrimitive(details.status); - replyPacketList->writeString(details.errorInfo); - } else { - replyPacketList->writePrimitive(false); + auto replyPacketList = NLPacketList::create(PacketType::EntityScriptGetStatusReply, QByteArray(), true, true); + replyPacketList->writePrimitive(messageID); + + EntityScriptDetails details; + if (_entitiesScriptEngine->getEntityScriptDetails(entityID, details)) { + replyPacketList->writePrimitive(true); + replyPacketList->writePrimitive(details.status); + replyPacketList->writeString(details.errorInfo); + } else { + replyPacketList->writePrimitive(false); + } + + auto nodeList = DependencyManager::get(); + nodeList->sendPacketList(std::move(replyPacketList), *senderNode); } - - auto nodeList = DependencyManager::get(); - nodeList->sendPacketList(std::move(replyPacketList), *senderNode); } void EntityScriptServer::run() { From b6893a01009df9ed786feec5d37996e884e471f5 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 19 Jan 2017 14:35:27 -0800 Subject: [PATCH 042/114] Keep Agents and EntityScriptServers from connecting if lacking permissions --- domain-server/src/DomainServer.cpp | 31 ++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 791b337764..5a5dd62c40 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -953,21 +953,32 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif // DTLSServerSession* dtlsSession = _isUsingDTLS ? _dtlsSessions[senderSockAddr] : NULL; if (nodeData->isAuthenticated()) { // if this authenticated node has any interest types, send back those nodes as well - limitedNodeList->eachNode([&](const SharedNodePointer& otherNode){ + limitedNodeList->eachNode([&](const SharedNodePointer& otherNode) { if (otherNode->getUUID() != node->getUUID() && nodeInterestSet.contains(otherNode->getType())) { - - // since we're about to add a node to the packet we start a segment - domainListPackets->startSegment(); - // don't send avatar nodes to other avatars, that will come from avatar mixer - domainListStream << *otherNode.data(); + // (1/19/17) Agents only need to connect to Entity Script Servers to perform administrative tasks + // related to entity server scripts. Only agents with rez permissions should be doing that, so + // if the agent does not have those permissions, we do not want them and the server to incur the + // overhead of connecting to one another. + bool shouldNotConnect = (node->getType() == NodeType::Agent && otherNode->getType() == NodeType::EntityScriptServer + && !node->getCanRez() && !node->getCanRezTmp()) + || (node->getType() == NodeType::EntityScriptServer && otherNode->getType() == NodeType::Agent + && !otherNode->getCanRez() && !otherNode->getCanRezTmp()); - // pack the secret that these two nodes will use to communicate with each other - domainListStream << connectionSecretForNodes(node, otherNode); + if (!shouldNotConnect) { + // since we're about to add a node to the packet we start a segment + domainListPackets->startSegment(); - // we've added the node we wanted so end the segment now - domainListPackets->endSegment(); + // don't send avatar nodes to other avatars, that will come from avatar mixer + domainListStream << *otherNode.data(); + + // pack the secret that these two nodes will use to communicate with each other + domainListStream << connectionSecretForNodes(node, otherNode); + + // we've added the node we wanted so end the segment now + domainListPackets->endSegment(); + } } }); } From c252d807823a1a5e70239d0b7256cf569e853d7b Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 19 Jan 2017 14:41:56 -0800 Subject: [PATCH 043/114] Fix EntityScriptDetails having incorrect scriptText --- libraries/script-engine/src/ScriptEngine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 4f6796a2a5..cedf5a4ed8 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -1431,7 +1431,7 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co auto fileName = isURL ? scriptOrURL : "EmbeddedEntityScript"; EntityScriptDetails newDetails; - newDetails.scriptText = isURL ? contents : scriptOrURL; + newDetails.scriptText = scriptOrURL; if (!success) { newDetails.status = ERROR_LOADING_SCRIPT; From 7cd19192d9114ef39a9f3aeb4806419fcadfbfe8 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 19 Jan 2017 15:00:30 -0800 Subject: [PATCH 044/114] Remove dead code in entityProperties.js --- scripts/system/html/js/entityProperties.js | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 286ccf5a38..a6523cdaf3 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -727,7 +727,6 @@ function loaded() { elServerScriptStatus.innerHTML = "Error running script"; elServerScriptError.style.display = "block"; } - //elServerScriptError.innerHTML = JSON.stringify(data) + "\n" + data.errorInfo;; elServerScriptError.innerHTML = data.errorInfo;; } else { elServerScriptStatus.innerHTML = "Not running"; From 7ba14a5f09488d522b7710dcd35cd6bba78c0028 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 19 Jan 2017 15:08:47 -0800 Subject: [PATCH 045/114] Fix AssignmentParentFinder.h include --- assignment-client/src/scripts/EntityScriptServer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index e251dd9841..40a3b4a276 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -15,7 +15,6 @@ #include #include -#include #include #include #include @@ -27,6 +26,8 @@ #include #include +#include "../entities/AssignmentParentFinder.h" + int EntityScriptServer::_entitiesScriptEngineCount = 0; EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : ThreadedAssignment(message) { From 465f5c6789e42b7c2df696c6e5a34a6aeea215f5 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 19 Jan 2017 15:09:16 -0800 Subject: [PATCH 046/114] Add getters to ScriptStatusRequest --- libraries/entities/src/EntityScriptingInterface.cpp | 4 ++-- libraries/networking/src/EntityScriptClient.cpp | 8 ++++---- libraries/networking/src/EntityScriptClient.h | 13 +++++++++---- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index ea02a2d5fa..26754335a0 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -681,7 +681,7 @@ bool EntityScriptingInterface::getServerScriptStatus(QUuid entityID, QScriptValu auto request = client->createScriptStatusRequest(entityID); connect(request, &GetScriptStatusRequest::finished, callback.engine(), [callback](GetScriptStatusRequest* request) mutable { QString statusString; - switch (request->status) { + switch (request->getStatus()) { case RUNNING: statusString = "running"; break; @@ -695,7 +695,7 @@ bool EntityScriptingInterface::getServerScriptStatus(QUuid entityID, QScriptValu statusString = ""; break; } - QScriptValueList args { request->responseReceived, request->isRunning, statusString, request->errorInfo }; + QScriptValueList args { request->getResponseReceived(), request->getIsRunning(), statusString, request->getErrorInfo() }; callback.call(QScriptValue(), args); request->deleteLater(); }); diff --git a/libraries/networking/src/EntityScriptClient.cpp b/libraries/networking/src/EntityScriptClient.cpp index b844cf4cf3..0e6cbed46d 100644 --- a/libraries/networking/src/EntityScriptClient.cpp +++ b/libraries/networking/src/EntityScriptClient.cpp @@ -17,10 +17,10 @@ GetScriptStatusRequest::~GetScriptStatusRequest() { void GetScriptStatusRequest::start() { auto client = DependencyManager::get(); client->getEntityServerScriptStatus(_entityID, [this](bool responseReceived, bool isRunning, EntityScriptStatus status, QString errorInfo) { - this->responseReceived = responseReceived; - this->isRunning = isRunning; - this->status = status; - this->errorInfo = errorInfo; + responseReceived = responseReceived; + isRunning = isRunning; + status = status; + errorInfo = errorInfo; emit finished(this); }); diff --git a/libraries/networking/src/EntityScriptClient.h b/libraries/networking/src/EntityScriptClient.h index c75f930f96..f32d78a6dd 100644 --- a/libraries/networking/src/EntityScriptClient.h +++ b/libraries/networking/src/EntityScriptClient.h @@ -32,10 +32,10 @@ public: Q_INVOKABLE void start(); - bool responseReceived; - bool isRunning; - EntityScriptStatus status; - QString errorInfo; + bool getResponseReceived() const { return _responseReceived; } + bool getIsRunning() const { return _isRunning; } + EntityScriptStatus getStatus() const { return _status; } + QString getErrorInfo() const { return _errorInfo; } signals: void finished(GetScriptStatusRequest* request); @@ -43,6 +43,11 @@ signals: private: QUuid _entityID; MessageID _messageID; + + bool _responseReceived; + bool _isRunning; + EntityScriptStatus _status; + QString _errorInfo; }; class EntityScriptClient : public QObject, public Dependency { From 9e17f63b8fa912cede6cabdcc221fb383c3a63aa Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 19 Jan 2017 15:10:26 -0800 Subject: [PATCH 047/114] Add comment to clarify rez/reztmp check in EntityScriptServer --- assignment-client/src/scripts/EntityScriptServer.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index 40a3b4a276..02a348df37 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -63,6 +63,8 @@ EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : ThreadedAssig static const QString ENTITY_SCRIPT_SERVER_LOGGING_NAME = "entity-script-server"; void EntityScriptServer::handleReloadEntityServerScriptPacket(QSharedPointer message, SharedNodePointer senderNode) { + // These are temporary checks until we can ensure that nodes eventually disconnect if the Domain Server stops telling them + // about each other. if (senderNode->getCanRez() || senderNode->getCanRezTmp()) { auto entityID = QUuid::fromRfc4122(message->read(NUM_BYTES_RFC4122_UUID)); @@ -75,6 +77,8 @@ void EntityScriptServer::handleReloadEntityServerScriptPacket(QSharedPointer message, SharedNodePointer senderNode) { + // These are temporary checks until we can ensure that nodes eventually disconnect if the Domain Server stops telling them + // about each other. if (senderNode->getCanRez() || senderNode->getCanRezTmp()) { MessageID messageID; message->readPrimitive(&messageID); From ff65d0c8cb9d7dee6266b5a459103e6a8ecfeb1c Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 19 Jan 2017 15:33:17 -0800 Subject: [PATCH 048/114] Fix property assignment in GetScriptStatusRequest --- libraries/networking/src/EntityScriptClient.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/networking/src/EntityScriptClient.cpp b/libraries/networking/src/EntityScriptClient.cpp index 0e6cbed46d..604a82fcca 100644 --- a/libraries/networking/src/EntityScriptClient.cpp +++ b/libraries/networking/src/EntityScriptClient.cpp @@ -17,10 +17,10 @@ GetScriptStatusRequest::~GetScriptStatusRequest() { void GetScriptStatusRequest::start() { auto client = DependencyManager::get(); client->getEntityServerScriptStatus(_entityID, [this](bool responseReceived, bool isRunning, EntityScriptStatus status, QString errorInfo) { - responseReceived = responseReceived; - isRunning = isRunning; - status = status; - errorInfo = errorInfo; + _responseReceived = responseReceived; + _isRunning = isRunning; + _status = status; + _errorInfo = errorInfo; emit finished(this); }); From 36a46c1bd6089789db19447d110f046c788538ab Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 19 Jan 2017 15:44:15 -0800 Subject: [PATCH 049/114] Add EntityScriptUtils --- libraries/networking/src/EntityScriptUtils.h | 21 ++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 libraries/networking/src/EntityScriptUtils.h diff --git a/libraries/networking/src/EntityScriptUtils.h b/libraries/networking/src/EntityScriptUtils.h new file mode 100644 index 0000000000..34ccdf23b6 --- /dev/null +++ b/libraries/networking/src/EntityScriptUtils.h @@ -0,0 +1,21 @@ +// +// EntityScriptUtils.h +// libraries/networking/src +// +// Created by Ryan Huffman on 2017/01/13 +// Copyright 2017 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_EntityScriptUtils_h +#define hifi_EntityScriptUtils_h + +enum EntityScriptStatus { + ERROR_LOADING_SCRIPT, + ERROR_RUNNING_SCRIPT, + RUNNING +}; + +#endif \ No newline at end of file From 091c353a8546663df604c29b82aa1770427efc05 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 19 Jan 2017 15:47:52 -0800 Subject: [PATCH 050/114] Add comment to endif in EntityScriptUtils --- libraries/networking/src/EntityScriptUtils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/EntityScriptUtils.h b/libraries/networking/src/EntityScriptUtils.h index 34ccdf23b6..ce57525a14 100644 --- a/libraries/networking/src/EntityScriptUtils.h +++ b/libraries/networking/src/EntityScriptUtils.h @@ -18,4 +18,4 @@ enum EntityScriptStatus { RUNNING }; -#endif \ No newline at end of file +#endif // hifi_EntityScriptUtils_h \ No newline at end of file From 20a82df9a0b33cd89dd56b83947c558d95bb2047 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 19 Jan 2017 14:02:32 -0800 Subject: [PATCH 051/114] Fix scripts not reloading in certain edge cases --- .../src/scripts/EntityScriptServer.cpp | 13 ++++--------- libraries/entities/src/EntityItem.h | 4 ---- libraries/script-engine/src/ScriptEngine.cpp | 7 +++++++ libraries/script-engine/src/ScriptEngine.h | 1 + 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index 02a348df37..579cd8ced6 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -216,12 +216,6 @@ void EntityScriptServer::resetEntitiesScriptEngine() { auto webSocketServerConstructorValue = newEngine->newFunction(WebSocketServerClass::constructor); newEngine->globalObject().setProperty("WebSocketServer", webSocketServerConstructorValue); - -// newEngine->setEmitScriptUpdatesFunction([this]() { -// SharedNodePointer entityServerNode = DependencyManager::get()->soloNodeOfType(NodeType::EntityServer); -// return !entityServerNode || isPhysicsEnabled(); -// }); - newEngine->registerGlobalObject("AvatarList", DependencyManager::get().data()); newEngine->registerGlobalObject("SoundCache", DependencyManager::get().data()); @@ -287,14 +281,15 @@ void EntityScriptServer::entityServerScriptChanging(const EntityItemID& entityID } void EntityScriptServer::checkAndCallPreload(const EntityItemID& entityID, const bool reload) { - if (_entityViewer.getTree() && !_shuttingDown) { + if (_entityViewer.getTree() && !_shuttingDown && _entitiesScriptEngine) { + auto details = _entitiesScriptEngine->getEntityScriptDetails(entityID); + EntityItemPointer entity = _entityViewer.getTree()->findEntityByEntityItemID(entityID); - if (entity && entity->shouldPreloadServerScript() && _entitiesScriptEngine) { + if (entity && (details.scriptText != entity->getServerScripts() || reload)) { QString scriptUrl = entity->getServerScripts(); scriptUrl = ResourceManager::normalizeURL(scriptUrl); qDebug() << "Loading entity server script" << scriptUrl << "for" << entityID; ScriptEngine::loadEntityScript(_entitiesScriptEngine, entityID, scriptUrl, reload); - entity->serverScriptHasPreloaded(); } } } diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index d4b62e74de..cb696dd91d 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -444,9 +444,6 @@ public: ((_loadedScript != _script) || (_loadedScriptTimestamp != _scriptTimestamp)); } void scriptHasPreloaded() { _loadedScript = _script; _loadedScriptTimestamp = _scriptTimestamp; } - bool shouldPreloadServerScript() const { return !_serverScripts.isEmpty() && ((_loadedServerScripts != _serverScripts)); } - void serverScriptHasPreloaded() { _loadedServerScripts = _serverScripts; } - bool getClientOnly() const { return _clientOnly; } void setClientOnly(bool clientOnly) { _clientOnly = clientOnly; } // if this entity is client-only, which avatar is it associated with? @@ -519,7 +516,6 @@ protected: QString _loadedScript; /// the value of _script when the last preload signal was sent quint64 _scriptTimestamp{ ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP }; /// the script loaded property used for forced reload QString _serverScripts; - QString _loadedServerScripts; /// the value of _scriptTimestamp when the last preload signal was sent // NOTE: on construction we want this to be different from _scriptTimestamp so we intentionally bump it diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index cedf5a4ed8..5cbd5c2739 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -1587,6 +1587,13 @@ void ScriptEngine::unloadAllEntityScripts() { #endif // DEBUG_ENGINE_STATE } +EntityScriptDetails ScriptEngine::getEntityScriptDetails(const EntityItemID& entityID) const { + if (_entityScripts.contains(entityID)) { + return _entityScripts[entityID]; + } + return EntityScriptDetails(); +} + void ScriptEngine::refreshFileScript(const EntityItemID& entityID) { if (!_entityScripts.contains(entityID)) { return; diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index e266ff3bc9..bdf542905a 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -149,6 +149,7 @@ public: const QStringList& params = QStringList()) override; Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const PointerEvent& event); Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const EntityItemID& otherID, const Collision& collision); + Q_INVOKABLE EntityScriptDetails getEntityScriptDetails(const EntityItemID& entityID) const; Q_INVOKABLE void requestGarbageCollection() { collectGarbage(); } From 3203e8c7c2ec7fdb3002106ea2515de770e20a7a Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 19 Jan 2017 15:49:40 -0800 Subject: [PATCH 052/114] Use Huffman's version of getEntityScriptDetails --- assignment-client/src/scripts/EntityScriptServer.cpp | 5 +++-- libraries/networking/src/EntityScriptClient.h | 2 +- libraries/script-engine/src/ScriptEngine.cpp | 7 ------- libraries/script-engine/src/ScriptEngine.h | 1 - 4 files changed, 4 insertions(+), 11 deletions(-) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index 579cd8ced6..6da935d0db 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -281,8 +281,9 @@ void EntityScriptServer::entityServerScriptChanging(const EntityItemID& entityID } void EntityScriptServer::checkAndCallPreload(const EntityItemID& entityID, const bool reload) { - if (_entityViewer.getTree() && !_shuttingDown && _entitiesScriptEngine) { - auto details = _entitiesScriptEngine->getEntityScriptDetails(entityID); + EntityScriptDetails details; + if (_entityViewer.getTree() && !_shuttingDown && _entitiesScriptEngine && + _entitiesScriptEngine->getEntityScriptDetails(entityID, details)) { EntityItemPointer entity = _entityViewer.getTree()->findEntityByEntityItemID(entityID); if (entity && (details.scriptText != entity->getServerScripts() || reload)) { diff --git a/libraries/networking/src/EntityScriptClient.h b/libraries/networking/src/EntityScriptClient.h index f32d78a6dd..d331b8ca31 100644 --- a/libraries/networking/src/EntityScriptClient.h +++ b/libraries/networking/src/EntityScriptClient.h @@ -73,4 +73,4 @@ private: void forceFailureOfPendingRequests(SharedNodePointer node); }; -#endif \ No newline at end of file +#endif diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 5cbd5c2739..cedf5a4ed8 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -1587,13 +1587,6 @@ void ScriptEngine::unloadAllEntityScripts() { #endif // DEBUG_ENGINE_STATE } -EntityScriptDetails ScriptEngine::getEntityScriptDetails(const EntityItemID& entityID) const { - if (_entityScripts.contains(entityID)) { - return _entityScripts[entityID]; - } - return EntityScriptDetails(); -} - void ScriptEngine::refreshFileScript(const EntityItemID& entityID) { if (!_entityScripts.contains(entityID)) { return; diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index bdf542905a..e266ff3bc9 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -149,7 +149,6 @@ public: const QStringList& params = QStringList()) override; Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const PointerEvent& event); Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const EntityItemID& otherID, const Collision& collision); - Q_INVOKABLE EntityScriptDetails getEntityScriptDetails(const EntityItemID& entityID) const; Q_INVOKABLE void requestGarbageCollection() { collectGarbage(); } From 07da0c5e9c8a356dcc8aa53f13976066a8d834bd Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 19 Jan 2017 15:58:55 -0800 Subject: [PATCH 053/114] Fix script loading bug --- assignment-client/src/scripts/EntityScriptServer.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index 6da935d0db..b2daabbd6c 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -281,12 +281,12 @@ void EntityScriptServer::entityServerScriptChanging(const EntityItemID& entityID } void EntityScriptServer::checkAndCallPreload(const EntityItemID& entityID, const bool reload) { - EntityScriptDetails details; - if (_entityViewer.getTree() && !_shuttingDown && _entitiesScriptEngine && - _entitiesScriptEngine->getEntityScriptDetails(entityID, details)) { + if (_entityViewer.getTree() && !_shuttingDown && _entitiesScriptEngine) { EntityItemPointer entity = _entityViewer.getTree()->findEntityByEntityItemID(entityID); - if (entity && (details.scriptText != entity->getServerScripts() || reload)) { + EntityScriptDetails details; + bool notRunning = !_entitiesScriptEngine->getEntityScriptDetails(entityID, details); + if (entity && (reload || notRunning || details.scriptText != entity->getServerScripts())) { QString scriptUrl = entity->getServerScripts(); scriptUrl = ResourceManager::normalizeURL(scriptUrl); qDebug() << "Loading entity server script" << scriptUrl << "for" << entityID; From b00435074e73eee66254b0646208ee5816b2cd9b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 19 Jan 2017 12:00:24 -0800 Subject: [PATCH 054/114] stop script engine when entity server goes away --- assignment-client/src/scripts/EntityScriptServer.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index b2daabbd6c..55e0973094 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -297,7 +297,11 @@ void EntityScriptServer::checkAndCallPreload(const EntityItemID& entityID, const void EntityScriptServer::nodeKilled(SharedNodePointer killedNode) { if (killedNode->getType() == NodeType::EntityServer) { - _entitiesScriptEngine->unloadAllEntityScripts(); + if (_entitiesScriptEngine) { + _entitiesScriptEngine->unloadAllEntityScripts(); + _entitiesScriptEngine->stop(); + } + resetEntitiesScriptEngine(); } } From a40c25ddbf1ab7d601e3280d06167f4d54fd28d3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 19 Jan 2017 14:17:23 -0800 Subject: [PATCH 055/114] fix repeated send of matching entities --- assignment-client/src/octree/OctreeSendThread.cpp | 5 ++--- libraries/entities/src/EntityTreeElement.cpp | 2 +- libraries/octree/src/Octree.cpp | 13 +++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index fc853820a3..7e88e47da8 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -316,9 +316,8 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode* int truePacketsSent = 0; int trueBytesSent = 0; int packetsSentThisInterval = 0; - bool isFullScene = !nodeData->getUsesFrustum() - || ((!viewFrustumChanged) && nodeData->getViewFrustumJustStoppedChanging()) - || nodeData->hasLodChanged(); + bool isFullScene = nodeData->getUsesFrustum() && + ((!viewFrustumChanged && nodeData->getViewFrustumJustStoppedChanging()) || nodeData->hasLodChanged()); bool somethingToSend = true; // assume we have something diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 7ece947e89..bbf1bfd3d5 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -287,7 +287,7 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData for (uint16_t i = 0; i < _entityItems.size(); i++) { EntityItemPointer entity = _entityItems[i]; bool includeThisEntity = true; - + if (!params.forceSendScene && entity->getLastChangedOnServer() < params.lastQuerySent) { includeThisEntity = false; } diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index a19a9709dc..d2d7aba517 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -899,7 +899,7 @@ int Octree::encodeTreeBitstream(OctreeElementPointer element, } // If we're at a element that is out of view, then we can return, because no nodes below us will be in view! - if (!params.recurseEverything && !element->isInView(params.viewFrustum)) { + if (params.usesFrustum && !params.recurseEverything && !element->isInView(params.viewFrustum)) { params.stopReason = EncodeBitstreamParams::OUT_OF_VIEW; return bytesWritten; } @@ -1015,7 +1015,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element, } ViewFrustum::intersection nodeLocationThisView = ViewFrustum::INSIDE; // assume we're inside - if (!params.recurseEverything) { + if (params.usesFrustum && !params.recurseEverything) { float boundaryDistance = boundaryDistanceForRenderLevel(element->getLevel() + params.boundaryLevelAdjust, params.octreeElementSizeScale); @@ -1176,7 +1176,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element, int originalIndex = indexOfChildren[i]; bool childIsInView = (childElement && - (params.recurseEverything || + (params.recurseEverything || !params.usesFrustum || (nodeLocationThisView == ViewFrustum::INSIDE) || // parent was fully in view, we can assume ALL children are (nodeLocationThisView == ViewFrustum::INTERSECT && childElement->isInView(params.viewFrustum)) // the parent intersects and the child is in view @@ -1189,7 +1189,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element, } } else { // Before we consider this further, let's see if it's in our LOD scope... - float boundaryDistance = params.recurseEverything ? 1 : + float boundaryDistance = params.recurseEverything || !params.usesFrustum ? 1 : boundaryDistanceForRenderLevel(childElement->getLevel() + params.boundaryLevelAdjust, params.octreeElementSizeScale); @@ -1211,7 +1211,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element, bool childIsOccluded = false; // assume it's not occluded - bool shouldRender = params.recurseEverything || + bool shouldRender = params.recurseEverything || !params.usesFrustum || childElement->calculateShouldRender(params.viewFrustum, params.octreeElementSizeScale, params.boundaryLevelAdjust); @@ -1451,7 +1451,8 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element, // called databits), then we wouldn't send the children. So those types of Octree's should tell us to keep // recursing, by returning TRUE in recurseChildrenWithData(). - if (params.recurseEverything || recurseChildrenWithData() || !oneAtBit(childrenDataBits, originalIndex)) { + if (params.recurseEverything || !params.usesFrustum + || recurseChildrenWithData() || !oneAtBit(childrenDataBits, originalIndex)) { // Allow the datatype a chance to determine if it really wants to recurse this tree. Usually this // will be true. But if the tree has already been encoded, we will skip this. From 0cb14ab25cf354d560312779eaaffd73a2899896 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 19 Jan 2017 14:59:01 -0800 Subject: [PATCH 056/114] whitespace fix in EntityTreeElement --- libraries/entities/src/EntityTreeElement.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index bbf1bfd3d5..7ece947e89 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -287,7 +287,7 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData for (uint16_t i = 0; i < _entityItems.size(); i++) { EntityItemPointer entity = _entityItems[i]; bool includeThisEntity = true; - + if (!params.forceSendScene && entity->getLastChangedOnServer() < params.lastQuerySent) { includeThisEntity = false; } From c5140ac695e3213c83c12ad7c09b24dc8f6347b8 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 19 Jan 2017 16:38:27 -0800 Subject: [PATCH 057/114] use ENTITY_ITEM_DEFAULT_SERVER_SCRIPTS in EntityItemProperties --- libraries/entities/src/EntityItemProperties.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index c1f6470490..775ecc2735 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -221,7 +221,7 @@ public: DEFINE_PROPERTY_REF(PROP_LAST_EDITED_BY, LastEditedBy, lastEditedBy, QUuid, ENTITY_ITEM_DEFAULT_LAST_EDITED_BY); - DEFINE_PROPERTY_REF(PROP_SERVER_SCRIPTS, ServerScripts, serverScripts, QString, ""); + DEFINE_PROPERTY_REF(PROP_SERVER_SCRIPTS, ServerScripts, serverScripts, QString, ENTITY_ITEM_DEFAULT_SERVER_SCRIPTS); static QString getBackgroundModeString(BackgroundMode mode); From 88ea6fa5896e71e3e6141439d337956b27d0826a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 19 Jan 2017 16:59:33 -0800 Subject: [PATCH 058/114] call script engine shutdown when assignment stopping --- assignment-client/src/scripts/EntityScriptServer.cpp | 4 +++- assignment-client/src/scripts/EntityScriptServer.h | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index 55e0973094..caf9a26582 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -254,7 +254,7 @@ void EntityScriptServer::clear() { _entityViewer.clear(); } -void EntityScriptServer::shutdown() { +void EntityScriptServer::shutdownScriptEngine() { if (_entitiesScriptEngine) { _entitiesScriptEngine->disconnectNonEssentialSignals(); // disconnect all slots/signals from the script engine, except essential } @@ -351,6 +351,8 @@ void EntityScriptServer::handleJurisdictionPacket(QSharedPointer()->setEntityTree(nullptr); diff --git a/assignment-client/src/scripts/EntityScriptServer.h b/assignment-client/src/scripts/EntityScriptServer.h index 55c639476b..9ea2d43aec 100644 --- a/assignment-client/src/scripts/EntityScriptServer.h +++ b/assignment-client/src/scripts/EntityScriptServer.h @@ -48,7 +48,8 @@ private: void resetEntitiesScriptEngine(); void clear(); - void shutdown(); + void shutdownScriptEngine(); + void addingEntity(const EntityItemID& entityID); void deletingEntity(const EntityItemID& entityID); void entityServerScriptChanging(const EntityItemID& entityID, const bool reload); From f807dee51eedfcb3d254d1d7ea5a847fb7302dcc Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 19 Jan 2017 17:29:10 -0800 Subject: [PATCH 059/114] Clear the tree when losing entity server --- assignment-client/src/scripts/EntityScriptServer.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index caf9a26582..1245ce5fcb 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -303,6 +303,8 @@ void EntityScriptServer::nodeKilled(SharedNodePointer killedNode) { } resetEntitiesScriptEngine(); + + _entityViewer.clear(); } } From 25bd6fa2c13e827859a04b7076cbab1106465548 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 20 Jan 2017 10:27:08 -0800 Subject: [PATCH 060/114] move recording interface to Agent/Application only --- assignment-client/src/Agent.cpp | 3 +++ interface/src/Application.cpp | 3 +++ libraries/script-engine/src/ScriptEngine.cpp | 3 --- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 234ae239cd..c462139ae9 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -376,6 +376,9 @@ void Agent::executeScript() { _scriptEngine->registerGlobalObject("EntityViewer", &_entityViewer); + auto recordingInterface = DependencyManager::get(); + _scriptEngine->registerGlobalObject("Recording", recordingInterface.data()); + // we need to make sure that init has been called for our EntityScriptingInterface // so that it actually has a jurisdiction listener when we ask it for it next entityScriptingInterface->init(); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5d32a830d0..ad2faa1047 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5485,6 +5485,9 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("Controller", scriptingInterface.data()); UserInputMapper::registerControllerTypes(scriptEngine); + auto recordingInterface = DependencyManager::get(); + _scriptEngine->registerGlobalObject("Recording", recordingInterface.data()); + // connect this script engines printedMessage signal to the global ScriptEngines these various messages connect(scriptEngine, &ScriptEngine::printedMessage, DependencyManager::get().data(), &ScriptEngines::onPrintedMessage); connect(scriptEngine, &ScriptEngine::errorMessage, DependencyManager::get().data(), &ScriptEngines::onErrorMessage); diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index cedf5a4ed8..dd1f5a707f 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -562,9 +562,6 @@ void ScriptEngine::init() { // constants globalObject().setProperty("TREE_SCALE", newVariant(QVariant(TREE_SCALE))); - auto recordingInterface = DependencyManager::get(); - registerGlobalObject("Recording", recordingInterface.data()); - registerGlobalObject("Assets", &_assetScriptingInterface); registerGlobalObject("Resources", DependencyManager::get().data()); } From eb033c797a01a2bdc17e2530f25acffb5c5a582f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 20 Jan 2017 10:36:57 -0800 Subject: [PATCH 061/114] fallback if local URL empty when loading default scripts --- libraries/script-engine/src/ScriptsModel.cpp | 67 ++++++++++---------- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/libraries/script-engine/src/ScriptsModel.cpp b/libraries/script-engine/src/ScriptsModel.cpp index 82ca26a03a..31f3a96fbd 100644 --- a/libraries/script-engine/src/ScriptsModel.cpp +++ b/libraries/script-engine/src/ScriptsModel.cpp @@ -156,39 +156,42 @@ void ScriptsModel::reloadDefaultFiles() { void ScriptsModel::requestDefaultFiles(QString marker) { QUrl url(defaultScriptsLocation()); - if (url.isLocalFile()) { - // if the url indicates a local directory, use QDirIterator - QString localDir = expandScriptUrl(url).toLocalFile(); - int localDirPartCount = localDir.split("/").size(); - if (localDir.endsWith("/")) { - localDirPartCount--; - } - #ifdef Q_OS_WIN - localDirPartCount++; // one for the drive letter - #endif - QDirIterator it(localDir, QStringList() << "*.js", QDir::Files, QDirIterator::Subdirectories); - while (it.hasNext()) { - QUrl jsFullPath = QUrl::fromLocalFile(it.next()); - QString jsPartialPath = jsFullPath.path().split("/").mid(localDirPartCount).join("/"); - jsFullPath = normalizeScriptURL(jsFullPath); - _treeNodes.append(new TreeNodeScript(jsPartialPath, jsFullPath.toString(), SCRIPT_ORIGIN_DEFAULT)); - } - _loadingScripts = false; - } else { - // the url indicates http(s), use QNetworkRequest - QUrlQuery query; - query.addQueryItem(PREFIX_PARAMETER_NAME, "."); - if (!marker.isEmpty()) { - query.addQueryItem(MARKER_PARAMETER_NAME, marker); - } - url.setQuery(query); + // targets that don't have a scripts folder in the appropriate location will have an empty URL here + if (!url.isEmpty()) { + if (url.isLocalFile()) { + // if the url indicates a local directory, use QDirIterator + QString localDir = expandScriptUrl(url).toLocalFile(); + int localDirPartCount = localDir.split("/").size(); + if (localDir.endsWith("/")) { + localDirPartCount--; + } +#ifdef Q_OS_WIN + localDirPartCount++; // one for the drive letter +#endif + QDirIterator it(localDir, QStringList() << "*.js", QDir::Files, QDirIterator::Subdirectories); + while (it.hasNext()) { + QUrl jsFullPath = QUrl::fromLocalFile(it.next()); + QString jsPartialPath = jsFullPath.path().split("/").mid(localDirPartCount).join("/"); + jsFullPath = normalizeScriptURL(jsFullPath); + _treeNodes.append(new TreeNodeScript(jsPartialPath, jsFullPath.toString(), SCRIPT_ORIGIN_DEFAULT)); + } + _loadingScripts = false; + } else { + // the url indicates http(s), use QNetworkRequest + QUrlQuery query; + query.addQueryItem(PREFIX_PARAMETER_NAME, "."); + if (!marker.isEmpty()) { + query.addQueryItem(MARKER_PARAMETER_NAME, marker); + } + url.setQuery(query); - QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); - QNetworkRequest request(url); - request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); - request.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); - QNetworkReply* reply = networkAccessManager.get(request); - connect(reply, SIGNAL(finished()), SLOT(downloadFinished())); + QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); + QNetworkRequest request(url); + request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); + request.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); + QNetworkReply* reply = networkAccessManager.get(request); + connect(reply, SIGNAL(finished()), SLOT(downloadFinished())); + } } } From 1b778a3ee04533d219dd4c61c6c3a18184dd8289 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 20 Jan 2017 10:42:07 -0800 Subject: [PATCH 062/114] fail quietly if local injection cannot happen --- libraries/audio/src/AudioInjector.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 48b44bd3d3..86cbc98d84 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -180,9 +180,6 @@ bool AudioInjector::injectLocally() { } else { qCDebug(audio) << "AudioInjector::injectLocally called without any data in Sound QByteArray"; } - - } else { - qCDebug(audio) << "AudioInjector::injectLocally cannot inject locally with no local audio interface present."; } return success; From 04e81c5db710fc5b418e43ee2160ff9fd4c5825a Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 20 Jan 2017 10:53:57 -0800 Subject: [PATCH 063/114] Fix interface build --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ad2faa1047..a0a77a9d7d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5486,7 +5486,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri UserInputMapper::registerControllerTypes(scriptEngine); auto recordingInterface = DependencyManager::get(); - _scriptEngine->registerGlobalObject("Recording", recordingInterface.data()); + scriptEngine->registerGlobalObject("Recording", recordingInterface.data()); // connect this script engines printedMessage signal to the global ScriptEngines these various messages connect(scriptEngine, &ScriptEngine::printedMessage, DependencyManager::get().data(), &ScriptEngines::onPrintedMessage); From 9c485dc61041267ac475440982536bba4815fdde Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 20 Jan 2017 10:59:46 -0800 Subject: [PATCH 064/114] don't restart script engine on shutting down with nodeKilled --- assignment-client/src/scripts/EntityScriptServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index 1245ce5fcb..ca48016feb 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -296,7 +296,7 @@ void EntityScriptServer::checkAndCallPreload(const EntityItemID& entityID, const } void EntityScriptServer::nodeKilled(SharedNodePointer killedNode) { - if (killedNode->getType() == NodeType::EntityServer) { + if (!_shuttingDown && killedNode->getType() == NodeType::EntityServer) { if (_entitiesScriptEngine) { _entitiesScriptEngine->unloadAllEntityScripts(); _entitiesScriptEngine->stop(); From 89e6e10c1df28042df3c9d9d63088cef963cd72f Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 20 Jan 2017 11:17:10 -0800 Subject: [PATCH 065/114] Add AvatarHashMap to EntityScriptServer --- assignment-client/src/entities/EntityServer.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index 23eec6197c..9474047fcb 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -17,6 +17,7 @@ #include "EntityServerConsts.h" #include "EntityNodeData.h" #include "AssignmentParentFinder.h" +#include const char* MODEL_SERVER_NAME = "Entity"; const char* MODEL_SERVER_LOGGING_TARGET_NAME = "entity-server"; @@ -62,6 +63,7 @@ OctreePointer EntityServer::createTree() { _entitySimulation = simpleSimulation; } + DependencyManager::set(); DependencyManager::registerInheritance(); DependencyManager::set(tree); From 2ca50153b37100811f4ca08ccf7e63cef8d69aa9 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 20 Jan 2017 11:17:41 -0800 Subject: [PATCH 066/114] Allow all node types to receive messages from Messages server --- assignment-client/src/messages/MessagesMixer.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/assignment-client/src/messages/MessagesMixer.cpp b/assignment-client/src/messages/MessagesMixer.cpp index 9555d1e160..7622c78f35 100644 --- a/assignment-client/src/messages/MessagesMixer.cpp +++ b/assignment-client/src/messages/MessagesMixer.cpp @@ -44,8 +44,7 @@ void MessagesMixer::handleMessages(QSharedPointer receivedMessa nodeList->eachMatchingNode( [&](const SharedNodePointer& node)->bool { - return node->getType() == NodeType::Agent && node->getActiveSocket() && - _channelSubscribers[channel].contains(node->getUUID()); + return node->getActiveSocket() && _channelSubscribers[channel].contains(node->getUUID()); }, [&](const SharedNodePointer& node) { auto packetList = MessagesClient::encodeMessagesPacket(channel, message, senderID); From 5c5c69fff30a46816eb85c6b553be2b94efac1fc Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 20 Jan 2017 11:20:48 -0800 Subject: [PATCH 067/114] setup the repeated message flusher on LogHandler thread --- libraries/shared/src/LogHandler.cpp | 7 ++++++- libraries/shared/src/LogHandler.h | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/libraries/shared/src/LogHandler.cpp b/libraries/shared/src/LogHandler.cpp index 35a3361c38..8e2c372bb6 100644 --- a/libraries/shared/src/LogHandler.cpp +++ b/libraries/shared/src/LogHandler.cpp @@ -186,7 +186,7 @@ void LogHandler::verboseMessageHandler(QtMsgType type, const QMessageLogContext& getInstance().printMessage((LogMsgType) type, context, message); } -const QString& LogHandler::addRepeatedMessageRegex(const QString& regexString) { +void LogHandler::setupRepeatedMessageFlusher() { static std::once_flag once; std::call_once(once, [&] { // setup our timer to flush the verbose logs every 5 seconds @@ -194,6 +194,11 @@ const QString& LogHandler::addRepeatedMessageRegex(const QString& regexString) { connect(logFlushTimer, &QTimer::timeout, this, &LogHandler::flushRepeatedMessages); logFlushTimer->start(VERBOSE_LOG_INTERVAL_SECONDS * 1000); }); +} + +const QString& LogHandler::addRepeatedMessageRegex(const QString& regexString) { + // make sure we setup the repeated message flusher, but do it on the LogHandler thread + QMetaObject::invokeMethod(this, "setupRepeatedMessageFlusher"); QMutexLocker lock(&_mutex); return *_repeatedMessageRegexes.insert(regexString); diff --git a/libraries/shared/src/LogHandler.h b/libraries/shared/src/LogHandler.h index f80fad4c6a..ea961a8d4c 100644 --- a/libraries/shared/src/LogHandler.h +++ b/libraries/shared/src/LogHandler.h @@ -53,6 +53,9 @@ public: const QString& addRepeatedMessageRegex(const QString& regexString); const QString& addOnlyOnceMessageRegex(const QString& regexString); +private slots: + void setupRepeatedMessageFlusher(); + private: LogHandler(); ~LogHandler(); From d55eba944087009be3ca233dcc279727d2de0249 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 20 Jan 2017 11:25:17 -0800 Subject: [PATCH 068/114] update AC monitor to launch 7 ACs --- server-console/src/main.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server-console/src/main.js b/server-console/src/main.js index b387aa5dd0..cdbb1d0a3c 100644 --- a/server-console/src/main.js +++ b/server-console/src/main.js @@ -582,7 +582,7 @@ function checkNewContent() { if (argv.noUpdater) { return; } - + // Start downloading content set var req = request.head({ url: HOME_CONTENT_URL @@ -859,7 +859,7 @@ function onContentLoaded() { if (dsPath && acPath) { domainServer = new Process('domain-server', dsPath, ["--get-temp-name"], logPath); - acMonitor = new ACMonitorProcess('ac-monitor', acPath, ['-n6', + acMonitor = new ACMonitorProcess('ac-monitor', acPath, ['-n7', '--log-directory', logPath, '--http-status-port', httpStatusPort], httpStatusPort, logPath); homeServer = new ProcessGroup('home', [domainServer, acMonitor]); From 8a691e8340b764c8aa088f2e1ea89df034572e32 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 20 Jan 2017 11:43:53 -0800 Subject: [PATCH 069/114] Remove AvatarHashMap from EntityServer --- .../src/entities/AssignmentParentFinder.cpp | 12 +++++++----- assignment-client/src/entities/EntityServer.cpp | 2 -- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/assignment-client/src/entities/AssignmentParentFinder.cpp b/assignment-client/src/entities/AssignmentParentFinder.cpp index ff167de9cf..b8737bdc63 100644 --- a/assignment-client/src/entities/AssignmentParentFinder.cpp +++ b/assignment-client/src/entities/AssignmentParentFinder.cpp @@ -33,11 +33,13 @@ SpatiallyNestableWeakPointer AssignmentParentFinder::find(QUuid parentID, bool& } // search avatars - auto avatarHashMap = DependencyManager::get(); - parent = avatarHashMap->getAvatarBySessionID(parentID); - if (!parent.expired()) { - success = true; - return parent; + if (DependencyManager::isSet()) { + auto avatarHashMap = DependencyManager::get(); + parent = avatarHashMap->getAvatarBySessionID(parentID); + if (!parent.expired()) { + success = true; + return parent; + } } success = false; diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index 9474047fcb..23eec6197c 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -17,7 +17,6 @@ #include "EntityServerConsts.h" #include "EntityNodeData.h" #include "AssignmentParentFinder.h" -#include const char* MODEL_SERVER_NAME = "Entity"; const char* MODEL_SERVER_LOGGING_TARGET_NAME = "entity-server"; @@ -63,7 +62,6 @@ OctreePointer EntityServer::createTree() { _entitySimulation = simpleSimulation; } - DependencyManager::set(); DependencyManager::registerInheritance(); DependencyManager::set(tree); From 6376068021896c69d7118660a054fde7fbf7c836 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 20 Jan 2017 13:54:46 -0800 Subject: [PATCH 070/114] fix usesFrustum check in OctreeQueryNode --- libraries/octree/src/OctreeQueryNode.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/octree/src/OctreeQueryNode.cpp b/libraries/octree/src/OctreeQueryNode.cpp index 01d2d85704..fe0c6c2a1f 100644 --- a/libraries/octree/src/OctreeQueryNode.cpp +++ b/libraries/octree/src/OctreeQueryNode.cpp @@ -156,7 +156,7 @@ bool OctreeQueryNode::updateCurrentViewFrustum() { return false; } - if (_usesFrustum) { + if (!_usesFrustum) { // this client does not use a view frustum so the view frustum for this query has not changed return false; } else { From 87404815794155f09f2401f6953a7384a6f18037 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 20 Jan 2017 13:54:10 -0800 Subject: [PATCH 071/114] Remove unnecessary const from `const bool` --- libraries/entities/src/EntityTree.cpp | 4 ++-- libraries/entities/src/EntityTree.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 38f413b0c5..d38cd295be 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -390,11 +390,11 @@ EntityItemPointer EntityTree::addEntity(const EntityItemID& entityID, const Enti return result; } -void EntityTree::emitEntityScriptChanging(const EntityItemID& entityItemID, const bool reload) { +void EntityTree::emitEntityScriptChanging(const EntityItemID& entityItemID, bool reload) { emit entityScriptChanging(entityItemID, reload); } -void EntityTree::emitEntityServerScriptChanging(const EntityItemID& entityItemID, const bool reload) { +void EntityTree::emitEntityServerScriptChanging(const EntityItemID& entityItemID, bool reload) { emit entityServerScriptChanging(entityItemID, reload); } diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 35aae904cd..cee1b10691 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -204,8 +204,8 @@ public: void entityChanged(EntityItemPointer entity); - void emitEntityScriptChanging(const EntityItemID& entityItemID, const bool reload); - void emitEntityServerScriptChanging(const EntityItemID& entityItemID, const bool reload); + void emitEntityScriptChanging(const EntityItemID& entityItemID, bool reload); + void emitEntityServerScriptChanging(const EntityItemID& entityItemID, bool reload); void setSimulation(EntitySimulationPointer simulation); EntitySimulationPointer getSimulation() const { return _simulation; } From 67951517b4e4a02724279150c25461e0d43e82c3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 20 Jan 2017 13:59:48 -0800 Subject: [PATCH 072/114] don't grab the JSON filters for each entity checked --- libraries/entities/src/EntityTreeElement.cpp | 56 ++++++++++---------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 7ece947e89..41e6fae054 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -284,6 +284,16 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData // entities for encoding. This is needed because we encode the element data at the "parent" level, and so we // need to handle the case where our sibling elements need encoding but we don't. if (!entityTreeElementExtraEncodeData->elementCompleted) { + + QJsonObject jsonFilters; + auto entityNodeData = dynamic_cast(params.nodeData); + + if (entityNodeData) { + // we have an EntityNodeData instance + // so we should assume that means we might have JSON filters to check + jsonFilters = entityNodeData->getJSONParameters(); + } + for (uint16_t i = 0; i < _entityItems.size(); i++) { EntityItemPointer entity = _entityItems[i]; bool includeThisEntity = true; @@ -291,35 +301,27 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData if (!params.forceSendScene && entity->getLastChangedOnServer() < params.lastQuerySent) { includeThisEntity = false; } - - auto entityNodeData = dynamic_cast(params.nodeData); - - if (entityNodeData) { - // we have an EntityNodeData instance - // so we should assume that means we might have JSON filters to check - auto jsonFilters = entityNodeData->getJSONParameters(); - - if (!jsonFilters.isEmpty()) { - - // if params include JSON filters, check if this entity matches - bool entityMatchesFilters = entity->matchesJSONFilters(jsonFilters); - - if (entityMatchesFilters) { - // we should include this entity unless it has already been excluded + + if (!jsonFilters.isEmpty()) { + + // if params include JSON filters, check if this entity matches + bool entityMatchesFilters = entity->matchesJSONFilters(jsonFilters); + + if (entityMatchesFilters) { + // we should include this entity unless it has already been excluded + includeThisEntity = includeThisEntity && true; + + // make sure this entity is in the set of entities sent last frame + entityNodeData->insertEntitySentLastFrame(entity->getID()); + + } else { + // we might include this entity if it matched in the previous frame + if (entityNodeData->sentEntityLastFrame(entity->getID())) { includeThisEntity = includeThisEntity && true; - - // make sure this entity is in the set of entities sent last frame - entityNodeData->insertEntitySentLastFrame(entity->getID()); - + + entityNodeData->removeEntitySentLastFrame(entity->getID()); } else { - // we might include this entity if it matched in the previous frame - if (entityNodeData->sentEntityLastFrame(entity->getID())) { - includeThisEntity = includeThisEntity && true; - - entityNodeData->removeEntitySentLastFrame(entity->getID()); - } else { - includeThisEntity = false; - } + includeThisEntity = false; } } } From 1e25b5012f4da0e1660bdabd28a40c6661aea8c5 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 20 Jan 2017 14:05:55 -0800 Subject: [PATCH 073/114] use a static_cast to get EntityNodeData --- libraries/entities/src/EntityTreeElement.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 41e6fae054..4cd82f223d 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -286,7 +286,7 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData if (!entityTreeElementExtraEncodeData->elementCompleted) { QJsonObject jsonFilters; - auto entityNodeData = dynamic_cast(params.nodeData); + auto entityNodeData = static_cast(params.nodeData); if (entityNodeData) { // we have an EntityNodeData instance From 7e9dffc02881c381d73f71cf7a3154302a2c61cf Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 20 Jan 2017 14:08:28 -0800 Subject: [PATCH 074/114] fix version number for EntityQuery JSON filter --- libraries/networking/src/udt/PacketHeaders.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index e2203389d0..89f30829fd 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -50,7 +50,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::EntityData: return VERSION_ENTITIES_SERVER_SCRIPTS; case PacketType::EntityQuery: - return VERSION_ENTITIES_JSON_FILTER; + return static_cast(EntityQueryPacketVersion::JsonFilter); case PacketType::AvatarIdentity: case PacketType::AvatarData: case PacketType::BulkAvatarData: diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 375043a370..aeeb15c057 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -201,7 +201,10 @@ const PacketVersion VERSION_WEB_ENTITIES_SUPPORT_DPI = 63; const PacketVersion VERSION_ENTITIES_ARROW_ACTION = 64; const PacketVersion VERSION_ENTITIES_LAST_EDITED_BY = 65; const PacketVersion VERSION_ENTITIES_SERVER_SCRIPTS = 66; -const PacketVersion VERSION_ENTITIES_JSON_FILTER = 67; + +enum class EntityQueryPacketVersion: PacketVersion { + JsonFilter = 18 +}; enum class AssetServerPacketVersion: PacketVersion { VegasCongestionControl = 19 From 5ef0bd7573f4f82cf72e810f02142d7a9b25266e Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 20 Jan 2017 14:10:42 -0800 Subject: [PATCH 075/114] remove weird extra whitespace --- libraries/entities/src/EntityItemProperties.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 572ca661a5..04c2ecec56 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -1021,7 +1021,7 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_PROPERTY_TO_MAP(PROP_X_P_NEIGHBOR_ID, XPNeighborID, xPNeighborID, EntityItemID); ADD_PROPERTY_TO_MAP(PROP_Y_P_NEIGHBOR_ID, YPNeighborID, yPNeighborID, EntityItemID); ADD_PROPERTY_TO_MAP(PROP_Z_P_NEIGHBOR_ID, ZPNeighborID, zPNeighborID, EntityItemID); - + ADD_PROPERTY_TO_MAP(PROP_PARENT_ID, ParentID, parentID, QUuid); ADD_PROPERTY_TO_MAP(PROP_PARENT_JOINT_INDEX, ParentJointIndex, parentJointIndex, uint16_t); From ee8898568d21ffc44173c207399670aa109640c1 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 20 Jan 2017 14:36:01 -0800 Subject: [PATCH 076/114] Remove const from getScript & getServerScripts --- libraries/entities/src/EntityItem.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index cb696dd91d..2fb91d0d77 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -254,13 +254,13 @@ public: using SpatiallyNestable::getQueryAACube; virtual AACube getQueryAACube(bool& success) const override; - const QString getScript() const { return _script; } + QString getScript() const { return _script; } void setScript(const QString& value) { _script = value; } quint64 getScriptTimestamp() const { return _scriptTimestamp; } void setScriptTimestamp(const quint64 value) { _scriptTimestamp = value; } - const QString getServerScripts() const { return _serverScripts; } + QString getServerScripts() const { return _serverScripts; } void setServerScripts(const QString& serverScripts) { _serverScripts = serverScripts; } const QString& getCollisionSoundURL() const { return _collisionSoundURL; } From 4e358f76fee0fb31c75f5ec2bf1e25cef90fae4c Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 20 Jan 2017 14:36:45 -0800 Subject: [PATCH 077/114] Remove trailing whitespace from EntityItemProperties.cpp --- .../entities/src/EntityItemProperties.cpp | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 572ca661a5..d95f162061 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -920,9 +920,9 @@ QScriptValue EntityItemProperties::entityPropertyFlagsToScriptValue(QScriptEngin static QHash _propertyStringsToEnums; void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue& object, EntityPropertyFlags& flags) { - + static std::once_flag initMap; - + std::call_once(initMap, [](){ ADD_PROPERTY_TO_MAP(PROP_VISIBLE, Visible, visible, bool); ADD_PROPERTY_TO_MAP(PROP_POSITION, Position, position, glm::vec3); @@ -1021,22 +1021,22 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_PROPERTY_TO_MAP(PROP_X_P_NEIGHBOR_ID, XPNeighborID, xPNeighborID, EntityItemID); ADD_PROPERTY_TO_MAP(PROP_Y_P_NEIGHBOR_ID, YPNeighborID, yPNeighborID, EntityItemID); ADD_PROPERTY_TO_MAP(PROP_Z_P_NEIGHBOR_ID, ZPNeighborID, zPNeighborID, EntityItemID); - + ADD_PROPERTY_TO_MAP(PROP_PARENT_ID, ParentID, parentID, QUuid); ADD_PROPERTY_TO_MAP(PROP_PARENT_JOINT_INDEX, ParentJointIndex, parentJointIndex, uint16_t); - + ADD_PROPERTY_TO_MAP(PROP_LOCAL_POSITION, LocalPosition, localPosition, glm::vec3); ADD_PROPERTY_TO_MAP(PROP_LOCAL_ROTATION, LocalRotation, localRotation, glm::quat); ADD_PROPERTY_TO_MAP(PROP_LOCAL_VELOCITY, LocalVelocity, localVelocity, glm::vec3); ADD_PROPERTY_TO_MAP(PROP_LOCAL_ANGULAR_VELOCITY, LocalAngularVelocity, localAngularVelocity, glm::vec3); - + ADD_PROPERTY_TO_MAP(PROP_JOINT_ROTATIONS_SET, JointRotationsSet, jointRotationsSet, QVector); ADD_PROPERTY_TO_MAP(PROP_JOINT_ROTATIONS, JointRotations, jointRotations, QVector); ADD_PROPERTY_TO_MAP(PROP_JOINT_TRANSLATIONS_SET, JointTranslationsSet, jointTranslationsSet, QVector); ADD_PROPERTY_TO_MAP(PROP_JOINT_TRANSLATIONS, JointTranslations, jointTranslations, QVector); - + ADD_PROPERTY_TO_MAP(PROP_SHAPE, Shape, shape, QString); - + ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_URL, Animation, animation, URL, url); ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_FPS, Animation, animation, FPS, fps); ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_FRAME_INDEX, Animation, animation, CurrentFrame, currentFrame); @@ -1045,10 +1045,10 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_FIRST_FRAME, Animation, animation, FirstFrame, firstFrame); ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_LAST_FRAME, Animation, animation, LastFrame, lastFrame); ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_HOLD, Animation, animation, Hold, hold); - + ADD_GROUP_PROPERTY_TO_MAP(PROP_SKYBOX_COLOR, Skybox, skybox, Color, color); ADD_GROUP_PROPERTY_TO_MAP(PROP_SKYBOX_URL, Skybox, skybox, URL, url); - + ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_SUN_MODEL_ENABLED, Stage, stage, SunModelEnabled, sunModelEnabled); ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_LATITUDE, Stage, stage, Latitude, latitude); ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_LONGITUDE, Stage, stage, Longitude, longitude); @@ -1056,15 +1056,15 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_DAY, Stage, stage, Day, day); ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_HOUR, Stage, stage, Hour, hour); ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_AUTOMATIC_HOURDAY, Stage, stage, AutomaticHourDay, automaticHourDay); - + ADD_PROPERTY_TO_MAP(PROP_FLYING_ALLOWED, FlyingAllowed, flyingAllowed, bool); ADD_PROPERTY_TO_MAP(PROP_GHOSTING_ALLOWED, GhostingAllowed, ghostingAllowed, bool); - + ADD_PROPERTY_TO_MAP(PROP_DPI, DPI, dpi, uint16_t); - + // FIXME - these are not yet handled //ADD_PROPERTY_TO_MAP(PROP_CREATED, Created, created, quint64); - + }); if (object.isString()) { @@ -1634,7 +1634,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int // NOTE: Spheres and Boxes are just special cases of Shape, and they need to include their PROP_SHAPE // when encoding/decoding edits because otherwise they can't polymorph to other shape types - if (properties.getType() == EntityTypes::Shape || + if (properties.getType() == EntityTypes::Shape || properties.getType() == EntityTypes::Box || properties.getType() == EntityTypes::Sphere) { READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SHAPE, QString, setShape); From 29b5daba3ae9673cd95b1af395e626d855aac833 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 20 Jan 2017 15:30:25 -0800 Subject: [PATCH 078/114] Revert input events script callbacks --- .../src/EntityTreeRenderer.cpp | 78 ++++++++++++------- 1 file changed, 49 insertions(+), 29 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 78d3f61047..a5d2970c98 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -104,35 +104,6 @@ void EntityTreeRenderer::resetEntitiesScriptEngine() { auto newEngine = new ScriptEngine(NO_SCRIPT, QString("Entities %1").arg(++_entitiesScriptEngineCount)); _entitiesScriptEngine = QSharedPointer(newEngine, entitiesScriptEngineDeleter); - auto makeSlotForSignal = [&](QString name) -> std::function { - return [newEngine, name](const EntityItemID& entityItemID, const PointerEvent& event) { - newEngine->callEntityScriptMethod(entityItemID, name, event); - }; - }; - - auto makeSlotForSignalNoEvent = [&](QString name) -> std::function { - return [newEngine, name](const EntityItemID& entityItemID) { - newEngine->callEntityScriptMethod(entityItemID, name); - }; - }; - - connect(this, &EntityTreeRenderer::mousePressOnEntity, newEngine, makeSlotForSignal("mousePressOnEntity")); - connect(this, &EntityTreeRenderer::mouseMoveOnEntity, newEngine, makeSlotForSignal("mouseMoveOnEntity")); - connect(this, &EntityTreeRenderer::mouseMoveOnEntity, newEngine, makeSlotForSignal("mouseMoveEvent")); - connect(this, &EntityTreeRenderer::mouseReleaseOnEntity, newEngine, makeSlotForSignal("mouseReleaseOnEntity")); - - connect(this, &EntityTreeRenderer::clickDownOnEntity, newEngine, makeSlotForSignal("clickDownOnEntity")); - connect(this, &EntityTreeRenderer::holdingClickOnEntity, newEngine, makeSlotForSignal("holdingClickOnEntity")); - connect(this, &EntityTreeRenderer::clickReleaseOnEntity, newEngine, makeSlotForSignal("clickReleaseOnEntity")); - - connect(this, &EntityTreeRenderer::hoverEnterEntity, newEngine, makeSlotForSignal("hoverEnterEntity")); - connect(this, &EntityTreeRenderer::hoverOverEntity, newEngine, makeSlotForSignal("hoverOverEntity")); - connect(this, &EntityTreeRenderer::hoverLeaveEntity, newEngine, makeSlotForSignal("hoverLeaveEntity")); - - connect(this, &EntityTreeRenderer::enterEntity, newEngine, makeSlotForSignalNoEvent("enterEntity")); - connect(this, &EntityTreeRenderer::leaveEntity, newEngine, makeSlotForSignalNoEvent("leaveEntity")); - - _scriptingServices->registerScriptEngineWithApplicationServices(_entitiesScriptEngine.data()); _entitiesScriptEngine->runInThread(); DependencyManager::get()->setEntitiesScriptEngine(_entitiesScriptEngine.data()); @@ -235,6 +206,7 @@ void EntityTreeRenderer::update() { // and we want to simulate this message here as well as in mouse move if (_lastPointerEventValid && !_currentClickingOnEntityID.isInvalidID()) { emit holdingClickOnEntity(_currentClickingOnEntityID, _lastPointerEvent); + _entitiesScriptEngine->callEntityScriptMethod(_currentClickingOnEntityID, "holdingClickOnEntity", _lastPointerEvent); } } @@ -328,6 +300,9 @@ bool EntityTreeRenderer::checkEnterLeaveEntities() { foreach(const EntityItemID& entityID, _currentEntitiesInside) { if (!entitiesContainingAvatar.contains(entityID)) { emit leaveEntity(entityID); + if (_entitiesScriptEngine) { + _entitiesScriptEngine->callEntityScriptMethod(entityID, "leaveEntity"); + } } } @@ -335,6 +310,9 @@ bool EntityTreeRenderer::checkEnterLeaveEntities() { foreach(const EntityItemID& entityID, entitiesContainingAvatar) { if (!_currentEntitiesInside.contains(entityID)) { emit enterEntity(entityID); + if (_entitiesScriptEngine) { + _entitiesScriptEngine->callEntityScriptMethod(entityID, "enterEntity"); + } } } _currentEntitiesInside = entitiesContainingAvatar; @@ -349,6 +327,9 @@ void EntityTreeRenderer::leaveAllEntities() { // for all of our previous containing entities, if they are no longer containing then send them a leave event foreach(const EntityItemID& entityID, _currentEntitiesInside) { emit leaveEntity(entityID); + if (_entitiesScriptEngine) { + _entitiesScriptEngine->callEntityScriptMethod(entityID, "leaveEntity"); + } } _currentEntitiesInside.clear(); forceRecheckEntities(); @@ -736,8 +717,15 @@ void EntityTreeRenderer::mousePressEvent(QMouseEvent* event) { emit mousePressOnEntity(rayPickResult.entityID, pointerEvent); + if (_entitiesScriptEngine) { + _entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "mousePressOnEntity", pointerEvent); + } + _currentClickingOnEntityID = rayPickResult.entityID; emit clickDownOnEntity(_currentClickingOnEntityID, pointerEvent); + if (_entitiesScriptEngine) { + _entitiesScriptEngine->callEntityScriptMethod(_currentClickingOnEntityID, "clickDownOnEntity", pointerEvent); + } _lastPointerEvent = pointerEvent; _lastPointerEventValid = true; @@ -768,6 +756,9 @@ void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event) { toPointerButton(*event), toPointerButtons(*event)); emit mouseReleaseOnEntity(rayPickResult.entityID, pointerEvent); + if (_entitiesScriptEngine) { + _entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "mouseReleaseOnEntity", pointerEvent); + } _lastPointerEvent = pointerEvent; _lastPointerEventValid = true; @@ -785,6 +776,9 @@ void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event) { toPointerButton(*event), toPointerButtons(*event)); emit clickReleaseOnEntity(_currentClickingOnEntityID, pointerEvent); + if (_entitiesScriptEngine) { + _entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "clickReleaseOnEntity", pointerEvent); + } } // makes it the unknown ID, we just released so we can't be clicking on anything @@ -813,6 +807,11 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) { emit mouseMoveOnEntity(rayPickResult.entityID, pointerEvent); + if (_entitiesScriptEngine) { + _entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "mouseMoveEvent", pointerEvent); + _entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "mouseMoveOnEntity", pointerEvent); + } + // handle the hover logic... // if we were previously hovering over an entity, and this new entity is not the same as our previous entity @@ -827,17 +826,26 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) { toPointerButton(*event), toPointerButtons(*event)); emit hoverLeaveEntity(_currentHoverOverEntityID, pointerEvent); + if (_entitiesScriptEngine) { + _entitiesScriptEngine->callEntityScriptMethod(_currentHoverOverEntityID, "hoverLeaveEntity", pointerEvent); + } } // If the new hover entity does not match the previous hover entity then we are entering the new one // this is true if the _currentHoverOverEntityID is known or unknown if (rayPickResult.entityID != _currentHoverOverEntityID) { emit hoverEnterEntity(rayPickResult.entityID, pointerEvent); + if (_entitiesScriptEngine) { + _entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "hoverEnterEntity", pointerEvent); + } } // and finally, no matter what, if we're intersecting an entity then we're definitely hovering over it, and // we should send our hover over event emit hoverOverEntity(rayPickResult.entityID, pointerEvent); + if (_entitiesScriptEngine) { + _entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "hoverOverEntity", pointerEvent); + } // remember what we're hovering over _currentHoverOverEntityID = rayPickResult.entityID; @@ -859,6 +867,9 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) { toPointerButton(*event), toPointerButtons(*event)); emit hoverLeaveEntity(_currentHoverOverEntityID, pointerEvent); + if (_entitiesScriptEngine) { + _entitiesScriptEngine->callEntityScriptMethod(_currentHoverOverEntityID, "hoverLeaveEntity", pointerEvent); + } _currentHoverOverEntityID = UNKNOWN_ENTITY_ID; // makes it the unknown ID } } @@ -875,6 +886,9 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) { toPointerButton(*event), toPointerButtons(*event)); emit holdingClickOnEntity(_currentClickingOnEntityID, pointerEvent); + if (_entitiesScriptEngine) { + _entitiesScriptEngine->callEntityScriptMethod(_currentClickingOnEntityID, "holdingClickOnEntity", pointerEvent); + } } } @@ -1042,10 +1056,16 @@ void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, cons // And now the entity scripts if (isCollisionOwner(myNodeID, entityTree, idA, collision)) { emit collisionWithEntity(idA, idB, collision); + if (_entitiesScriptEngine) { + _entitiesScriptEngine->callEntityScriptMethod(idA, "collisionWithEntity", idB, collision); + } } if (isCollisionOwner(myNodeID, entityTree, idB, collision)) { emit collisionWithEntity(idB, idA, collision); + if (_entitiesScriptEngine) { + _entitiesScriptEngine->callEntityScriptMethod(idB, "collisionWithEntity", idA, collision); + } } } From 888d7ab03d62cc73f7ebb849773eb7858853dc2f Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 20 Jan 2017 15:33:48 -0800 Subject: [PATCH 079/114] Add exception information to script status --- libraries/script-engine/src/ScriptEngine.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index cedf5a4ed8..2dd95aedac 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -147,19 +147,19 @@ static bool hasCorrectSyntax(const QScriptProgram& program, ScriptEngine* report return true; } -static bool hadUncaughtExceptions(QScriptEngine& engine, const QString& fileName, ScriptEngine* reportingEngine) { +static bool hadUncaughtExceptions(QScriptEngine& engine, const QString& fileName, ScriptEngine* reportingEngine, QString& exceptionMessage = QString()) { if (engine.hasUncaughtException()) { const auto backtrace = engine.uncaughtExceptionBacktrace(); const auto exception = engine.uncaughtException().toString(); const auto line = QString::number(engine.uncaughtExceptionLineNumber()); engine.clearExceptions(); - auto message = QString(SCRIPT_EXCEPTION_FORMAT).arg(exception, fileName, line); + exceptionMessage = QString(SCRIPT_EXCEPTION_FORMAT).arg(exception, fileName, line); if (!backtrace.empty()) { static const auto lineSeparator = "\n "; - message += QString("\n[Backtrace]%1%2").arg(lineSeparator, backtrace.join(lineSeparator)); + exceptionMessage += QString("\n[Backtrace]%1%2").arg(lineSeparator, backtrace.join(lineSeparator)); } - reportingEngine->scriptErrorMessage(qPrintable(message)); + reportingEngine->scriptErrorMessage(qPrintable(exceptionMessage)); return true; } return false; @@ -1472,9 +1472,11 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co }); testConstructor = sandbox.evaluate(program); } - if (hadUncaughtExceptions(sandbox, program.fileName(), this)) { + + QString exceptionMessage; + if (hadUncaughtExceptions(sandbox, program.fileName(), this, exceptionMessage)) { newDetails.status = ERROR_RUNNING_SCRIPT; - newDetails.errorInfo = "Exception"; + newDetails.errorInfo = exceptionMessage; _entityScripts[entityID] = newDetails; return; From ad70431c26056c706855ab29fb7b764866214fd1 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 20 Jan 2017 15:34:22 -0800 Subject: [PATCH 080/114] Fix edit.js server script status getting reset when changing properties --- scripts/system/edit.js | 31 ++++++++++--------- .../system/libraries/entitySelectionTool.js | 12 +++---- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 50bf22a565..29396614a6 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -1443,7 +1443,6 @@ var PropertiesTool = function (opts) { }; function updateScriptStatus(info) { - print("Got status: ", info); info.type = "server_script_status"; webView.emitScriptEvent(JSON.stringify(info)); }; @@ -1457,26 +1456,28 @@ var PropertiesTool = function (opts) { }); } - selectionManager.addEventListener(function () { + selectionManager.addEventListener(function (selectionUpdated) { var data = { type: 'update' }; - resetScriptStatus(); + if (selectionUpdated) { + resetScriptStatus(); - if (selectionManager.selections.length !== 1) { - if (statusMonitor !== null) { - statusMonitor.stop(); - statusMonitor = null; + if (selectionManager.selections.length !== 1) { + if (statusMonitor !== null) { + statusMonitor.stop(); + statusMonitor = null; + } + currentSelectedEntityID = null; + } else if (currentSelectedEntityID != selectionManager.selections[0]) { + if (statusMonitor !== null) { + statusMonitor.stop(); + } + var entityID = selectionManager.selections[0]; + currentSelectedEntityID = entityID; + statusMonitor = new ServerScriptStatusMonitor(entityID, updateScriptStatus); } - currentSelectedEntityID = null; - } else if (currentSelectedEntityID != selectionManager.selections[0]) { - if (statusMonitor !== null) { - statusMonitor.stop(); - } - var entityID = selectionManager.selections[0]; - currentSelectedEntityID = entityID; - statusMonitor = new ServerScriptStatusMonitor(entityID, updateScriptStatus); } var selections = []; diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index d31f4cb722..7fe29bec67 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -113,7 +113,7 @@ SelectionManager = (function() { that.selections.push(entityID); } - that._update(); + that._update(true); }; that.addEntity = function(entityID, toggleSelection) { @@ -132,7 +132,7 @@ SelectionManager = (function() { } } - that._update(); + that._update(true); }; that.removeEntity = function(entityID) { @@ -140,15 +140,15 @@ SelectionManager = (function() { if (idx >= 0) { that.selections.splice(idx, 1); } - that._update(); + that._update(true); }; that.clearSelections = function() { that.selections = []; - that._update(); + that._update(true); }; - that._update = function() { + that._update = function(selectionUpdated) { if (that.selections.length == 0) { that.localDimensions = null; that.localPosition = null; @@ -205,7 +205,7 @@ SelectionManager = (function() { for (var i = 0; i < listeners.length; i++) { try { - listeners[i](); + listeners[i](selectionUpdated === true); } catch (e) { print("EntitySelectionTool got exception: " + JSON.stringify(e)); } From 4d6eea9a63a6c447aade4d462e590ac8d679bec7 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Fri, 20 Jan 2017 16:40:32 -0800 Subject: [PATCH 081/114] Updated WASAPI plugins to force dwChannelMask = KSAUDIO_SPEAKER_DIRECTOUT --- cmake/externals/wasapi/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/externals/wasapi/CMakeLists.txt b/cmake/externals/wasapi/CMakeLists.txt index 7cfca4f3ba..b085eefb0c 100644 --- a/cmake/externals/wasapi/CMakeLists.txt +++ b/cmake/externals/wasapi/CMakeLists.txt @@ -6,8 +6,8 @@ if (WIN32) include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} - URL http://hifi-public.s3.amazonaws.com/dependencies/qtaudio_wasapi5.zip - URL_MD5 0530753e855ffc00232cc969bf1c84a8 + URL http://hifi-public.s3.amazonaws.com/dependencies/qtaudio_wasapi6.zip + URL_MD5 fcac808c1ba0b0f5b44ea06e2612ebab CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" From e9c6e9dd5c3264de333f978e5bce156bbaf81820 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 20 Jan 2017 16:43:11 -0800 Subject: [PATCH 082/114] Move MessageID to ClientServerUtils --- assignment-client/src/assets/AssetServer.cpp | 1 + .../src/assets/SendAssetTask.cpp | 1 + .../src/assets/UploadAssetTask.cpp | 2 ++ .../src/scripts/EntityScriptServer.cpp | 3 +-- libraries/networking/src/AssetClient.h | 1 + libraries/networking/src/AssetUtils.h | 5 +---- libraries/networking/src/ClientServerUtils.h | 21 +++++++++++++++++++ libraries/networking/src/EntityScriptClient.h | 3 +-- 8 files changed, 29 insertions(+), 8 deletions(-) create mode 100644 libraries/networking/src/ClientServerUtils.h diff --git a/assignment-client/src/assets/AssetServer.cpp b/assignment-client/src/assets/AssetServer.cpp index 017ffd94f1..a7927fd5b4 100644 --- a/assignment-client/src/assets/AssetServer.cpp +++ b/assignment-client/src/assets/AssetServer.cpp @@ -27,6 +27,7 @@ #include "NodeType.h" #include "SendAssetTask.h" #include "UploadAssetTask.h" +#include const QString ASSET_SERVER_LOGGING_TARGET_NAME = "asset-server"; diff --git a/assignment-client/src/assets/SendAssetTask.cpp b/assignment-client/src/assets/SendAssetTask.cpp index d2b3c6c256..ca8733d660 100644 --- a/assignment-client/src/assets/SendAssetTask.cpp +++ b/assignment-client/src/assets/SendAssetTask.cpp @@ -21,6 +21,7 @@ #include #include "AssetUtils.h" +#include "ClientServerUtils.h" SendAssetTask::SendAssetTask(QSharedPointer message, const SharedNodePointer& sendToNode, const QDir& resourcesDir) : QRunnable(), diff --git a/assignment-client/src/assets/UploadAssetTask.cpp b/assignment-client/src/assets/UploadAssetTask.cpp index e09619a3cc..7e8e94c34d 100644 --- a/assignment-client/src/assets/UploadAssetTask.cpp +++ b/assignment-client/src/assets/UploadAssetTask.cpp @@ -18,6 +18,8 @@ #include #include +#include "ClientServerUtils.h" + UploadAssetTask::UploadAssetTask(QSharedPointer receivedMessage, SharedNodePointer senderNode, const QDir& resourcesDir) : diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index b2daabbd6c..466842b80b 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -11,8 +11,6 @@ #include "EntityScriptServer.h" -#include "EntityScriptUtils.h" - #include #include #include @@ -26,6 +24,7 @@ #include #include +#include "ClientServerUtils.h" #include "../entities/AssignmentParentFinder.h" int EntityScriptServer::_entitiesScriptEngineCount = 0; diff --git a/libraries/networking/src/AssetClient.h b/libraries/networking/src/AssetClient.h index be1cafa232..c0d58cd8e6 100644 --- a/libraries/networking/src/AssetClient.h +++ b/libraries/networking/src/AssetClient.h @@ -21,6 +21,7 @@ #include #include "AssetUtils.h" +#include "ClientServerUtils.h" #include "LimitedNodeList.h" #include "Node.h" #include "ReceivedMessage.h" diff --git a/libraries/networking/src/AssetUtils.h b/libraries/networking/src/AssetUtils.h index b0008271d2..4137193274 100644 --- a/libraries/networking/src/AssetUtils.h +++ b/libraries/networking/src/AssetUtils.h @@ -19,7 +19,6 @@ #include #include -using MessageID = uint32_t; using DataOffset = int64_t; using AssetPath = QString; @@ -27,8 +26,6 @@ using AssetHash = QString; using AssetMapping = std::map; using AssetPathList = QStringList; -const MessageID INVALID_MESSAGE_ID = 0; - const size_t SHA256_HASH_LENGTH = 32; const size_t SHA256_HASH_HEX_LENGTH = 64; const uint64_t MAX_UPLOAD_SIZE = 1000 * 1000 * 1000; // 1GB @@ -66,4 +63,4 @@ bool isValidFilePath(const AssetPath& path); bool isValidPath(const AssetPath& path); bool isValidHash(const QString& hashString); -#endif +#endif // hifi_AssetUtils_h diff --git a/libraries/networking/src/ClientServerUtils.h b/libraries/networking/src/ClientServerUtils.h new file mode 100644 index 0000000000..234c6d7c91 --- /dev/null +++ b/libraries/networking/src/ClientServerUtils.h @@ -0,0 +1,21 @@ + +// +// ClientServerUtils.h +// libraries/networking/src +// +// Created by Ryan Huffman on 2017/01/20 +// Copyright 2017 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_ClientServerUtils_h +#define hifi_ClientServerUtils_h + +#include + +using MessageID = uint32_t; +const MessageID INVALID_MESSAGE_ID = 0; + +#endif // hifi_ClientServerUtils_h diff --git a/libraries/networking/src/EntityScriptClient.h b/libraries/networking/src/EntityScriptClient.h index d331b8ca31..926521d9b8 100644 --- a/libraries/networking/src/EntityScriptClient.h +++ b/libraries/networking/src/EntityScriptClient.h @@ -12,6 +12,7 @@ #ifndef hifi_EntityScriptClient_h #define hifi_EntityScriptClient_h +#include "ClientServerUtils.h" #include "LimitedNodeList.h" #include "ReceivedMessage.h" #include "AssetUtils.h" @@ -20,8 +21,6 @@ #include #include -using MessageID = uint32_t; - using GetScriptStatusCallback = std::function; class GetScriptStatusRequest : public QObject { From be9b19e534b1e8b3d04c96980b8d7476bbe76198 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 20 Jan 2017 16:43:35 -0800 Subject: [PATCH 083/114] Fix default param ref failing on non-MSVC builds --- libraries/script-engine/src/ScriptEngine.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 2dd95aedac..41b2c633aa 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -147,19 +147,22 @@ static bool hasCorrectSyntax(const QScriptProgram& program, ScriptEngine* report return true; } -static bool hadUncaughtExceptions(QScriptEngine& engine, const QString& fileName, ScriptEngine* reportingEngine, QString& exceptionMessage = QString()) { +static bool hadUncaughtExceptions(QScriptEngine& engine, const QString& fileName, ScriptEngine* reportingEngine, QString* exceptionMessage = nullptr) { if (engine.hasUncaughtException()) { const auto backtrace = engine.uncaughtExceptionBacktrace(); const auto exception = engine.uncaughtException().toString(); const auto line = QString::number(engine.uncaughtExceptionLineNumber()); engine.clearExceptions(); - exceptionMessage = QString(SCRIPT_EXCEPTION_FORMAT).arg(exception, fileName, line); + QString message = QString(SCRIPT_EXCEPTION_FORMAT).arg(exception, fileName, line); if (!backtrace.empty()) { static const auto lineSeparator = "\n "; - exceptionMessage += QString("\n[Backtrace]%1%2").arg(lineSeparator, backtrace.join(lineSeparator)); + message += QString("\n[Backtrace]%1%2").arg(lineSeparator, backtrace.join(lineSeparator)); + } + reportingEngine->scriptErrorMessage(qPrintable(message)); + if (exceptionMessage) { + *exceptionMessage = message; } - reportingEngine->scriptErrorMessage(qPrintable(exceptionMessage)); return true; } return false; @@ -1474,7 +1477,7 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co } QString exceptionMessage; - if (hadUncaughtExceptions(sandbox, program.fileName(), this, exceptionMessage)) { + if (hadUncaughtExceptions(sandbox, program.fileName(), this, &exceptionMessage)) { newDetails.status = ERROR_RUNNING_SCRIPT; newDetails.errorInfo = exceptionMessage; _entityScripts[entityID] = newDetails; From e1b313d9aa2ff05cf240d912223e540e03c757a4 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Fri, 20 Jan 2017 16:43:46 -0800 Subject: [PATCH 084/114] Remove support for floating-point audio (not needed) --- libraries/audio-client/src/AudioClient.cpp | 43 +++------------- libraries/audio/src/AudioRingBuffer.h | 59 ++++++++-------------- 2 files changed, 29 insertions(+), 73 deletions(-) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index e2d2dd499b..1e3dc11338 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -433,21 +433,8 @@ bool adjustedFormatForAudioDevice(const QAudioDeviceInfo& audioDevice, for (int channelCount : (desiredAudioFormat.channelCount() == 1 ? inputChannels : outputChannels)) { for (int sampleRate : sampleRates) { - // int16_t samples adjustedAudioFormat.setChannelCount(channelCount); adjustedAudioFormat.setSampleRate(sampleRate); - adjustedAudioFormat.setSampleSize(16); - adjustedAudioFormat.setSampleType(QAudioFormat::SignedInt); - - if (audioDevice.isFormatSupported(adjustedAudioFormat)) { - return true; - } - - // float samples - adjustedAudioFormat.setChannelCount(channelCount); - adjustedAudioFormat.setSampleRate(sampleRate); - adjustedAudioFormat.setSampleSize(32); - adjustedAudioFormat.setSampleType(QAudioFormat::Float); if (audioDevice.isFormatSupported(adjustedAudioFormat)) { return true; @@ -1558,15 +1545,11 @@ float AudioClient::gainForSource(float distance, float volume) { return gain; } -qint64 AudioClient::AudioOutputIODevice::readData(char* data, qint64 maxSize) { - - // data can be int16_t* or float* - int sampleSize = _audio->_outputFormat.sampleSize() / 8; - bool isFloat = _audio->_outputFormat.sampleType() == QAudioFormat::SampleType::Float; +qint64 AudioClient::AudioOutputIODevice::readData(char * data, qint64 maxSize) { // samples requested from OUTPUT_CHANNEL_COUNT int deviceChannelCount = _audio->_outputFormat.channelCount(); - int samplesRequested = (int)(maxSize / sampleSize) * OUTPUT_CHANNEL_COUNT / deviceChannelCount; + int samplesRequested = (int)(maxSize / AudioConstants::SAMPLE_SIZE) * OUTPUT_CHANNEL_COUNT / deviceChannelCount; int samplesPopped; int bytesWritten; @@ -1576,24 +1559,14 @@ qint64 AudioClient::AudioOutputIODevice::readData(char* data, qint64 maxSize) { AudioRingBuffer::ConstIterator lastPopOutput = _receivedAudioStream.getLastPopOutput(); // if required, upmix or downmix to deviceChannelCount - if (isFloat) { - if (deviceChannelCount == OUTPUT_CHANNEL_COUNT) { - lastPopOutput.readSamples((float*)data, samplesPopped); - } else if (deviceChannelCount > OUTPUT_CHANNEL_COUNT) { - lastPopOutput.readSamplesWithUpmix((float*)data, samplesPopped, deviceChannelCount - OUTPUT_CHANNEL_COUNT); - } else { - lastPopOutput.readSamplesWithDownmix((float*)data, samplesPopped); - } + if (deviceChannelCount == OUTPUT_CHANNEL_COUNT) { + lastPopOutput.readSamples((int16_t*)data, samplesPopped); + } else if (deviceChannelCount > OUTPUT_CHANNEL_COUNT) { + lastPopOutput.readSamplesWithUpmix((int16_t*)data, samplesPopped, deviceChannelCount - OUTPUT_CHANNEL_COUNT); } else { - if (deviceChannelCount == OUTPUT_CHANNEL_COUNT) { - lastPopOutput.readSamples((int16_t*)data, samplesPopped); - } else if (deviceChannelCount > OUTPUT_CHANNEL_COUNT) { - lastPopOutput.readSamplesWithUpmix((int16_t*)data, samplesPopped, deviceChannelCount - OUTPUT_CHANNEL_COUNT); - } else { - lastPopOutput.readSamplesWithDownmix((int16_t*)data, samplesPopped); - } + lastPopOutput.readSamplesWithDownmix((int16_t*)data, samplesPopped); } - bytesWritten = (samplesPopped * sampleSize) * deviceChannelCount / OUTPUT_CHANNEL_COUNT; + bytesWritten = (samplesPopped * AudioConstants::SAMPLE_SIZE) * deviceChannelCount / OUTPUT_CHANNEL_COUNT; } else { // nothing on network, don't grab anything from injectors, and just return 0s // this will flood the log: qCDebug(audioclient, "empty/partial network buffer"); diff --git a/libraries/audio/src/AudioRingBuffer.h b/libraries/audio/src/AudioRingBuffer.h index 38ca319156..29e7a9e998 100644 --- a/libraries/audio/src/AudioRingBuffer.h +++ b/libraries/audio/src/AudioRingBuffer.h @@ -103,11 +103,10 @@ public: ConstIterator operator+(int i); ConstIterator operator-(int i); - // dest can be int16_t* or float* - template void readSamples(T* dest, int numSamples); - template void readSamplesWithFade(T* dest, int numSamples, float fade); - template void readSamplesWithUpmix(T* dest, int numSamples, int numExtraChannels); - template void readSamplesWithDownmix(T* dest, int numSamples); + void readSamples(int16_t* dest, int numSamples); + void readSamplesWithFade(int16_t* dest, int numSamples, float fade); + void readSamplesWithUpmix(int16_t* dest, int numSamples, int numExtraChannels); + void readSamplesWithDownmix(int16_t* dest, int numSamples); private: int16_t* atShiftedBy(int i); @@ -204,28 +203,6 @@ inline int16_t* AudioRingBuffer::ConstIterator::atShiftedBy(int i) { return _bufferFirst + i; } -inline AudioRingBuffer::ConstIterator AudioRingBuffer::nextOutput() const { - return ConstIterator(_buffer, _bufferLength, _nextOutput); -} - -inline AudioRingBuffer::ConstIterator AudioRingBuffer::lastFrameWritten() const { - return ConstIterator(_buffer, _bufferLength, _endOfLastWrite) - _numFrameSamples; -} - -// -// dest can be int16_t* or float* -// -template -inline void AudioRingBuffer::ConstIterator::readSamples(T* dest, int numSamples) { - int16_t* at = _at; - for (int i = 0; i < numSamples; i++) { - *dest++ = (T)*at; - at = (at == _bufferLast) ? _bufferFirst : at + 1; - } -} - -// fast path for int16_t* -template<> inline void AudioRingBuffer::ConstIterator::readSamples(int16_t* dest, int numSamples) { auto samplesToEnd = _bufferLast - _at + 1; @@ -241,17 +218,16 @@ inline void AudioRingBuffer::ConstIterator::readSamples(int16_t* dest, int numSa } } -template -inline void AudioRingBuffer::ConstIterator::readSamplesWithFade(T* dest, int numSamples, float fade) { +inline void AudioRingBuffer::ConstIterator::readSamplesWithFade(int16_t* dest, int numSamples, float fade) { int16_t* at = _at; for (int i = 0; i < numSamples; i++) { - *dest++ = (T)(*at * fade); + *dest = (float)*at * fade; + ++dest; at = (at == _bufferLast) ? _bufferFirst : at + 1; } } -template -inline void AudioRingBuffer::ConstIterator::readSamplesWithUpmix(T* dest, int numSamples, int numExtraChannels) { +inline void AudioRingBuffer::ConstIterator::readSamplesWithUpmix(int16_t* dest, int numSamples, int numExtraChannels) { int16_t* at = _at; for (int i = 0; i < numSamples/2; i++) { @@ -262,16 +238,15 @@ inline void AudioRingBuffer::ConstIterator::readSamplesWithUpmix(T* dest, int nu at = (at == _bufferLast) ? _bufferFirst : at + 1; // write 2 + N samples - *dest++ = (T)left; - *dest++ = (T)right; + *dest++ = left; + *dest++ = right; for (int n = 0; n < numExtraChannels; n++) { - *dest++ = (T)0; + *dest++ = 0; } } } -template -inline void AudioRingBuffer::ConstIterator::readSamplesWithDownmix(T* dest, int numSamples) { +inline void AudioRingBuffer::ConstIterator::readSamplesWithDownmix(int16_t* dest, int numSamples) { int16_t* at = _at; for (int i = 0; i < numSamples/2; i++) { @@ -282,8 +257,16 @@ inline void AudioRingBuffer::ConstIterator::readSamplesWithDownmix(T* dest, int at = (at == _bufferLast) ? _bufferFirst : at + 1; // write 1 sample - *dest++ = (T)((left + right) / 2); + *dest++ = (int16_t)((left + right) / 2); } } +inline AudioRingBuffer::ConstIterator AudioRingBuffer::nextOutput() const { + return ConstIterator(_buffer, _bufferLength, _nextOutput); +} + +inline AudioRingBuffer::ConstIterator AudioRingBuffer::lastFrameWritten() const { + return ConstIterator(_buffer, _bufferLength, _endOfLastWrite) - _numFrameSamples; +} + #endif // hifi_AudioRingBuffer_h From 9b1cd52fb493162f6ced94a50e3585a6e3ea8485 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 12 Jan 2017 15:08:27 -0800 Subject: [PATCH 085/114] Add the ability to get the context that a script is running in --- assignment-client/src/Agent.cpp | 4 ++-- interface/src/Application.cpp | 2 +- .../src/EntityTreeRenderer.cpp | 2 +- libraries/script-engine/src/ScriptEngine.cpp | 19 ++++++++++++++++++- libraries/script-engine/src/ScriptEngine.h | 19 ++++++++++++++++++- libraries/script-engine/src/ScriptEngines.cpp | 7 ++++--- libraries/script-engine/src/ScriptEngines.h | 4 +++- 7 files changed, 47 insertions(+), 10 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index c462139ae9..1a034e5c8a 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -68,7 +68,7 @@ Agent::Agent(ReceivedMessage& message) : DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); - DependencyManager::set(); + DependencyManager::set(ScriptEngine::AGENT_SCRIPT); auto& packetReceiver = DependencyManager::get()->getPacketReceiver(); @@ -321,7 +321,7 @@ void Agent::scriptRequestFinished() { } void Agent::executeScript() { - _scriptEngine = std::unique_ptr(new ScriptEngine(_scriptContents, _payload)); + _scriptEngine = std::unique_ptr(new ScriptEngine(ScriptEngine::AGENT_SCRIPT, _scriptContents, _payload)); _scriptEngine->setParent(this); // be the parent of the script engine so it gets moved when we do // setup an Avatar for the script to use diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a0a77a9d7d..9a452e3d63 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -459,7 +459,7 @@ bool setupEssentials(int& argc, char** argv) { // Set dependencies DependencyManager::set(std::bind(&Application::getUserAgent, qApp)); DependencyManager::set(); - DependencyManager::set(); + DependencyManager::set(ScriptEngine::CLIENT_SCRIPT); DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index a5d2970c98..d277fd540f 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -101,7 +101,7 @@ void EntityTreeRenderer::resetEntitiesScriptEngine() { // Keep a ref to oldEngine until newEngine is ready so EntityScriptingInterface has something to use auto oldEngine = _entitiesScriptEngine; - auto newEngine = new ScriptEngine(NO_SCRIPT, QString("Entities %1").arg(++_entitiesScriptEngineCount)); + auto newEngine = new ScriptEngine(ScriptEngine::ENTITY_CLIENT_SCRIPT, NO_SCRIPT, QString("Entities %1").arg(++_entitiesScriptEngineCount)); _entitiesScriptEngine = QSharedPointer(newEngine, entitiesScriptEngineDeleter); _scriptingServices->registerScriptEngineWithApplicationServices(_entitiesScriptEngine.data()); diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index ab9d4af417..b823ce858b 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -168,7 +168,8 @@ static bool hadUncaughtExceptions(QScriptEngine& engine, const QString& fileName return false; } -ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNameString) : +ScriptEngine::ScriptEngine(Context context, const QString& scriptContents, const QString& fileNameString) : + _context(context), _scriptContents(scriptContents), _timerFunctionMap(), _fileNameString(fileNameString), @@ -183,6 +184,22 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam setProcessEventsInterval(MSECS_PER_SECOND); } +QString ScriptEngine::getContext() const { + switch (_context) { + case CLIENT_SCRIPT: + return "client"; + case ENTITY_CLIENT_SCRIPT: + return "entity_client"; + case ENTITY_SERVER_SCRIPT: + return "entity_server"; + case AGENT_SCRIPT: + return "agent"; + default: + return "unknown"; + } + return "unknown"; +} + ScriptEngine::~ScriptEngine() { scriptInfoMessage("Script Engine shutting down:" + getFilename()); diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index e266ff3bc9..32d81b9511 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -72,8 +72,17 @@ public: class ScriptEngine : public QScriptEngine, public ScriptUser, public EntitiesScriptEngineProvider { Q_OBJECT + Q_PROPERTY(QString context READ getContext) public: - ScriptEngine(const QString& scriptContents = NO_SCRIPT, const QString& fileNameString = QString("")); + + enum Context { + CLIENT_SCRIPT, + ENTITY_CLIENT_SCRIPT, + ENTITY_SERVER_SCRIPT, + AGENT_SCRIPT + }; + + ScriptEngine(Context context, const QString& scriptContents = NO_SCRIPT, const QString& fileNameString = QString("")); ~ScriptEngine(); /// run the script in a dedicated thread. This will have the side effect of evalulating @@ -124,6 +133,12 @@ public: /// to scripts. we may not need this to be invokable void loadURL(const QUrl& scriptURL, bool reload); + Q_INVOKABLE QString getContext() const; + Q_INVOKABLE bool isClientScript() const { return _context == CLIENT_SCRIPT; } + Q_INVOKABLE bool isEntityClientScript() const { return _context == ENTITY_CLIENT_SCRIPT; } + Q_INVOKABLE bool isEntityServerScript() const { return _context == ENTITY_SERVER_SCRIPT; } + Q_INVOKABLE bool isAgentScript() const { return _context == AGENT_SCRIPT; } + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // NOTE - these are intended to be public interfaces available to scripts Q_INVOKABLE void addEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler); @@ -230,6 +245,8 @@ protected: void doWithEnvironment(const EntityItemID& entityID, const QUrl& sandboxURL, std::function operation); void callWithEnvironment(const EntityItemID& entityID, const QUrl& sandboxURL, QScriptValue function, QScriptValue thisObject, QScriptValueList args); + Context _context; + QString _scriptContents; QString _parentURL; std::atomic _isFinished { false }; diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index 74acb2ae6a..eb3ab4abec 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -62,8 +62,9 @@ void ScriptEngines::onErrorLoadingScript(const QString& url) { emit errorLoadingScript(url, scriptName); } -ScriptEngines::ScriptEngines() - : _scriptsLocationHandle("scriptsLocation", DESKTOP_LOCATION) +ScriptEngines::ScriptEngines(ScriptEngine::Context context) + : _context(context), + _scriptsLocationHandle("scriptsLocation", DESKTOP_LOCATION) { _scriptsModelFilter.setSourceModel(&_scriptsModel); _scriptsModelFilter.sort(0, Qt::AscendingOrder); @@ -453,7 +454,7 @@ ScriptEngine* ScriptEngines::loadScript(const QUrl& scriptFilename, bool isUserL return scriptEngine; } - scriptEngine = new ScriptEngine(NO_SCRIPT, ""); + scriptEngine = new ScriptEngine(_context, NO_SCRIPT, ""); scriptEngine->setUserLoaded(isUserLoaded); connect(scriptEngine, &ScriptEngine::doneRunning, this, [scriptEngine] { scriptEngine->deleteLater(); diff --git a/libraries/script-engine/src/ScriptEngines.h b/libraries/script-engine/src/ScriptEngines.h index b0f0e24ac6..2fadfc81f8 100644 --- a/libraries/script-engine/src/ScriptEngines.h +++ b/libraries/script-engine/src/ScriptEngines.h @@ -20,6 +20,7 @@ #include #include +#include "ScriptEngine.h" #include "ScriptsModel.h" #include "ScriptsModelFilter.h" @@ -34,7 +35,7 @@ class ScriptEngines : public QObject, public Dependency { public: using ScriptInitializer = std::function; - ScriptEngines(); + ScriptEngines(ScriptEngine::Context context); void registerScriptInitializer(ScriptInitializer initializer); void loadScripts(); @@ -100,6 +101,7 @@ protected: void onScriptEngineError(const QString& scriptFilename); void launchScriptEngine(ScriptEngine* engine); + ScriptEngine::Context _context; QReadWriteLock _scriptEnginesHashLock; QHash _scriptEnginesHash; QSet _allKnownScriptEngines; From 95024d2b8092f2798f49a251778699682ffb1d25 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 23 Jan 2017 09:30:30 -0800 Subject: [PATCH 086/114] Add ENTITY_SERVER_SCRIPT context to ac server --- assignment-client/src/scripts/EntityScriptServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index c1e53dda17..b798536ab2 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -41,7 +41,7 @@ EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : ThreadedAssig DependencyManager::set(); DependencyManager::set(); - DependencyManager::set(); + DependencyManager::set(ENTITY_SERVER_SCRIPT); auto& packetReceiver = DependencyManager::get()->getPacketReceiver(); From cba0b295e8f5ef8ca57e63dc30b8a611d24e66bc Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 23 Jan 2017 15:09:08 -0500 Subject: [PATCH 087/114] connect audio injector signal to scripting --- libraries/script-engine/src/ScriptAudioInjector.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/script-engine/src/ScriptAudioInjector.cpp b/libraries/script-engine/src/ScriptAudioInjector.cpp index 2ec30ad4dd..c0ad2debd9 100644 --- a/libraries/script-engine/src/ScriptAudioInjector.cpp +++ b/libraries/script-engine/src/ScriptAudioInjector.cpp @@ -32,7 +32,7 @@ void injectorFromScriptValue(const QScriptValue& object, ScriptAudioInjector*& o ScriptAudioInjector::ScriptAudioInjector(AudioInjector* injector) : _injector(injector) { - + QObject::connect(injector, &AudioInjector::finished, this, &ScriptAudioInjector::finished); } ScriptAudioInjector::~ScriptAudioInjector() { From fb8d2e34fb46bea9e9b483ed6e05a061a1c60371 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Jan 2017 13:14:53 -0800 Subject: [PATCH 088/114] fix needless reinterpret_cast for DomainServerNodeData --- domain-server/src/DomainGatekeeper.cpp | 12 ++++++------ domain-server/src/DomainServer.cpp | 14 +++++++------- domain-server/src/DomainServerSettingsManager.cpp | 4 ++-- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index 97f3e1a697..3d4e48f94a 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -107,7 +107,7 @@ void DomainGatekeeper::processConnectRequestPacket(QSharedPointer(node->getLinkedData()); + DomainServerNodeData* nodeData = static_cast(node->getLinkedData()); nodeData->setSendingSockAddr(message->getSenderSockAddr()); // guard against patched agents asking to hear about other agents @@ -128,12 +128,12 @@ void DomainGatekeeper::processConnectRequestPacket(QSharedPointergetSenderSockAddr() - << "with hardware address" << nodeConnection.hardwareAddress + << "with hardware address" << nodeConnection.hardwareAddress << "and machine fingerprint" << nodeConnection.machineFingerprint; } } -NodePermissions DomainGatekeeper::setPermissionsForUser(bool isLocalUser, QString verifiedUsername, const QHostAddress& senderAddress, +NodePermissions DomainGatekeeper::setPermissionsForUser(bool isLocalUser, QString verifiedUsername, const QHostAddress& senderAddress, const QString& hardwareAddress, const QUuid& machineFingerprint) { NodePermissions userPerms; @@ -283,7 +283,7 @@ void DomainGatekeeper::updateNodePermissions() { QString hardwareAddress; QUuid machineFingerprint; - DomainServerNodeData* nodeData = reinterpret_cast(node->getLinkedData()); + DomainServerNodeData* nodeData = static_cast(node->getLinkedData()); if (nodeData) { hardwareAddress = nodeData->getHardwareAddress(); machineFingerprint = nodeData->getMachineFingerprint(); @@ -336,7 +336,7 @@ SharedNodePointer DomainGatekeeper::processAssignmentConnectRequest(const NodeCo // add the new node SharedNodePointer newNode = addVerifiedNodeFromConnectRequest(nodeConnection); - DomainServerNodeData* nodeData = reinterpret_cast(newNode->getLinkedData()); + DomainServerNodeData* nodeData = static_cast(newNode->getLinkedData()); // set assignment related data on the linked data for this node nodeData->setAssignmentUUID(matchingQueuedAssignment->getUUID()); @@ -458,7 +458,7 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect newNode->setPermissions(userPerms); // grab the linked data for our new node so we can set the username - DomainServerNodeData* nodeData = reinterpret_cast(newNode->getLinkedData()); + DomainServerNodeData* nodeData = static_cast(newNode->getLinkedData()); // if we have a username from the connect request, set it on the DomainServerNodeData nodeData->setUsername(username); diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 0f7923519b..aebec1e317 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -841,7 +841,7 @@ void DomainServer::processListRequestPacket(QSharedPointer mess sendingNode->setLocalSocket(nodeRequestData.localSockAddr); // update the NodeInterestSet in case there have been any changes - DomainServerNodeData* nodeData = reinterpret_cast(sendingNode->getLinkedData()); + DomainServerNodeData* nodeData = static_cast(sendingNode->getLinkedData()); // guard against patched agents asking to hear about other agents auto safeInterestSet = nodeRequestData.interestList.toSet(); @@ -945,7 +945,7 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif // always send the node their own UUID back QDataStream domainListStream(domainListPackets.get()); - DomainServerNodeData* nodeData = reinterpret_cast(node->getLinkedData()); + DomainServerNodeData* nodeData = static_cast(node->getLinkedData()); // store the nodeInterestSet on this DomainServerNodeData, in case it has changed auto& nodeInterestSet = nodeData->getNodeInterestSet(); @@ -994,7 +994,7 @@ QUuid DomainServer::connectionSecretForNodes(const SharedNodePointer& nodeA, con secretUUID = QUuid::createUuid(); // set it on the other Node's sessionSecretHash - reinterpret_cast(nodeBData)->getSessionSecretHash().insert(nodeA->getUUID(), secretUUID); + static_cast(nodeBData)->getSessionSecretHash().insert(nodeA->getUUID(), secretUUID); } return secretUUID; @@ -1124,7 +1124,7 @@ void DomainServer::processRequestAssignmentPacket(QSharedPointer()->eachNode([&](const SharedNodePointer& node){ - DomainServerNodeData* nodeData = reinterpret_cast(node->getLinkedData()); + DomainServerNodeData* nodeData = static_cast(node->getLinkedData()); if (!nodeData->getAssignmentUUID().isNull() && !nodeData->getWalletUUID().isNull()) { // check if we have a non-finalized transaction for this node to add this amount to @@ -1556,7 +1556,7 @@ QJsonObject DomainServer::jsonObjectForNode(const SharedNodePointer& node) { nodeJson[JSON_KEY_UPTIME] = QString::number(double(QDateTime::currentMSecsSinceEpoch() - node->getWakeTimestamp()) / 1000.0); // if the node has pool information, add it - DomainServerNodeData* nodeData = reinterpret_cast(node->getLinkedData()); + DomainServerNodeData* nodeData = static_cast(node->getLinkedData()); // add the node username, if it exists nodeJson[JSON_KEY_USERNAME] = nodeData->getUsername(); @@ -1687,7 +1687,7 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url // enumerate the NodeList to find the assigned nodes nodeList->eachNode([this, &assignedNodesJSON](const SharedNodePointer& node){ - DomainServerNodeData* nodeData = reinterpret_cast(node->getLinkedData()); + DomainServerNodeData* nodeData = static_cast(node->getLinkedData()); if (!nodeData->getAssignmentUUID().isNull()) { // add the node using the UUID as the key @@ -1775,7 +1775,7 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url if (matchingNode) { // create a QJsonDocument with the stats QJsonObject QJsonObject statsObject = - reinterpret_cast(matchingNode->getLinkedData())->getStatsJSONObject(); + static_cast(matchingNode->getLinkedData())->getStatsJSONObject(); // add the node type to the JSON data for output purposes statsObject["node_type"] = NodeType::getNodeTypeName(matchingNode->getType()).toLower().replace(' ', '-'); diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index 5e1d747604..a0b80875b0 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -725,7 +725,7 @@ void DomainServerSettingsManager::processNodeKickRequestPacket(QSharedPointer(matchingNode->getLinkedData()); + DomainServerNodeData* nodeData = static_cast(matchingNode->getLinkedData()); if (nodeData) { // mac address first NodePermissionsKey macAddressKey(nodeData->getHardwareAddress(), 0); @@ -807,7 +807,7 @@ void DomainServerSettingsManager::processUsernameFromIDRequestPacket(QSharedPoin usernameFromIDReplyPacket->writeString(verifiedUsername); // now put in the machine fingerprint - DomainServerNodeData* nodeData = reinterpret_cast(matchingNode->getLinkedData()); + DomainServerNodeData* nodeData = static_cast(matchingNode->getLinkedData()); machineFingerprint = nodeData ? nodeData->getMachineFingerprint() : QUuid(); usernameFromIDReplyPacket->write(machineFingerprint.toRfc4122()); } else { From 1802e1520db6fe59809f2a5f10a3417d7240e1ed Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Jan 2017 13:15:48 -0800 Subject: [PATCH 089/114] change some dynamic_cast to static_cast for DomainServerNodeData --- domain-server/src/DomainServer.cpp | 60 +++++++++++++++--------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index aebec1e317..7f142b6ef8 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -107,7 +107,7 @@ DomainServer::DomainServer(int argc, char* argv[]) : qRegisterMetaType("DomainServerWebSessionData"); qRegisterMetaTypeStreamOperators("DomainServerWebSessionData"); - + // make sure we hear about newly connected nodes from our gatekeeper connect(&_gatekeeper, &DomainGatekeeper::connectedNode, this, &DomainServer::handleConnectedNode); @@ -281,7 +281,7 @@ bool DomainServer::optionallyReadX509KeyAndCertificate() { QString keyPassphraseString = QProcessEnvironment::systemEnvironment().value(X509_KEY_PASSPHRASE_ENV); qDebug() << "Reading certificate file at" << certPath << "for HTTPS."; - qDebug() << "Reading key file at" << keyPath << "for HTTPS."; + qDebug() << "Reading key file at" << keyPath << "for HTTPS."; QFile certFile(certPath); certFile.open(QIODevice::ReadOnly); @@ -528,12 +528,12 @@ void DomainServer::setupNodeListAndAssignments() { packetReceiver.registerListener(PacketType::DomainServerPathQuery, this, "processPathQueryPacket"); packetReceiver.registerListener(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"); packetReceiver.registerListener(PacketType::NodeKickRequest, &_settingsManager, "processNodeKickRequestPacket"); packetReceiver.registerListener(PacketType::UsernameFromIDRequest, &_settingsManager, "processUsernameFromIDRequestPacket"); - + // register the gatekeeper for the packets it needs to receive packetReceiver.registerListener(PacketType::DomainConnectRequest, &_gatekeeper, "processConnectRequestPacket"); packetReceiver.registerListener(PacketType::ICEPing, &_gatekeeper, "processICEPingPacket"); @@ -542,7 +542,7 @@ void DomainServer::setupNodeListAndAssignments() { packetReceiver.registerListener(PacketType::ICEServerHeartbeatDenied, this, "processICEServerHeartbeatDenialPacket"); packetReceiver.registerListener(PacketType::ICEServerHeartbeatACK, this, "processICEServerHeartbeatACK"); - + // add whatever static assignments that have been parsed to the queue addStaticAssignmentsToQueue(); @@ -811,18 +811,18 @@ void DomainServer::populateDefaultStaticAssignmentsExcludingTypes(const QSet mess // update this node's sockets in case they have changed sendingNode->setPublicSocket(nodeRequestData.publicSockAddr); sendingNode->setLocalSocket(nodeRequestData.localSockAddr); - + // update the NodeInterestSet in case there have been any changes DomainServerNodeData* nodeData = static_cast(sendingNode->getLinkedData()); @@ -928,14 +928,14 @@ void DomainServer::handleConnectedNode(SharedNodePointer newNode) { void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const HifiSockAddr &senderSockAddr) { const int NUM_DOMAIN_LIST_EXTENDED_HEADER_BYTES = NUM_BYTES_RFC4122_UUID + NUM_BYTES_RFC4122_UUID + 2; - + // setup the extended header for the domain list packets // this data is at the beginning of each of the domain list packets QByteArray extendedHeader(NUM_DOMAIN_LIST_EXTENDED_HEADER_BYTES, 0); QDataStream extendedHeaderStream(&extendedHeader, QIODevice::WriteOnly); - + auto limitedNodeList = DependencyManager::get(); - + extendedHeaderStream << limitedNodeList->getSessionUUID(); extendedHeaderStream << node->getUUID(); extendedHeaderStream << node->getPermissions(); @@ -958,7 +958,7 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif limitedNodeList->eachNode([&](const SharedNodePointer& otherNode){ if (otherNode->getUUID() != node->getUUID() && nodeInterestSet.contains(otherNode->getType())) { - + // since we're about to add a node to the packet we start a segment domainListPackets->startSegment(); @@ -974,7 +974,7 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif }); } } - + // send an empty list to the node, in case there were no other nodes domainListPackets->closeCurrentPacket(true); @@ -983,8 +983,8 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif } QUuid DomainServer::connectionSecretForNodes(const SharedNodePointer& nodeA, const SharedNodePointer& nodeB) { - DomainServerNodeData* nodeAData = dynamic_cast(nodeA->getLinkedData()); - DomainServerNodeData* nodeBData = dynamic_cast(nodeB->getLinkedData()); + DomainServerNodeData* nodeAData = static_cast(nodeA->getLinkedData()); + DomainServerNodeData* nodeBData = static_cast(nodeB->getLinkedData()); if (nodeAData && nodeBData) { QUuid& secretUUID = nodeAData->getSessionSecretHash()[nodeB->getUUID()]; @@ -1020,7 +1020,7 @@ void DomainServer::broadcastNewNode(const SharedNodePointer& addedNode) { [&](const SharedNodePointer& node)->bool { if (node->getLinkedData() && node->getActiveSocket() && node != addedNode) { // is the added Node in this node's interest list? - DomainServerNodeData* nodeData = dynamic_cast(node->getLinkedData()); + DomainServerNodeData* nodeData = static_cast(node->getLinkedData()); return nodeData->getNodeInterestSet().contains(addedNode->getType()); } else { return false; @@ -1510,7 +1510,7 @@ void DomainServer::sendHeartbeatToIceServer() { } void DomainServer::processNodeJSONStatsPacket(QSharedPointer packetList, SharedNodePointer sendingNode) { - auto nodeData = dynamic_cast(sendingNode->getLinkedData()); + auto nodeData = static_cast(sendingNode->getLinkedData()); if (nodeData) { nodeData->updateJSONStats(packetList->getMessage()); } @@ -1624,23 +1624,23 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url if (connection->requestOperation() == QNetworkAccessManager::GetOperation && assignmentRegex.indexIn(url.path()) != -1) { QUuid nodeUUID = QUuid(assignmentRegex.cap(1)); - + auto matchingNode = nodeList->nodeWithUUID(nodeUUID); - + // don't handle if we don't have a matching node if (!matchingNode) { return false; } - - auto nodeData = dynamic_cast(matchingNode->getLinkedData()); - + + auto nodeData = static_cast(matchingNode->getLinkedData()); + // don't handle if we don't have node data for this node if (!nodeData) { return false; } - + SharedAssignmentPointer matchingAssignment = _allAssignments.value(nodeData->getAssignmentUUID()); - + // check if we have an assignment that matches this temp UUID, and it is a scripted assignment if (matchingAssignment && matchingAssignment->getType() == Assignment::AgentType) { // we have a matching assignment and it is for the right type, have the HTTP manager handle it @@ -1655,7 +1655,7 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url return true; } - + // request not handled return false; } @@ -2247,7 +2247,7 @@ void DomainServer::addStaticAssignmentsToQueue() { // if the domain-server has just restarted, // check if there are static assignments that we need to throw into the assignment queue auto sharedAssignments = _allAssignments.values(); - + // sort the assignments to put the server/mixer assignments first qSort(sharedAssignments.begin(), sharedAssignments.end(), [](SharedAssignmentPointer a, SharedAssignmentPointer b){ if (a->getType() == b->getType()) { @@ -2258,9 +2258,9 @@ void DomainServer::addStaticAssignmentsToQueue() { return a->getType() != Assignment::AgentType; } }); - + auto staticAssignment = sharedAssignments.begin(); - + while (staticAssignment != sharedAssignments.end()) { // add any of the un-matched static assignments to the queue @@ -2385,7 +2385,7 @@ void DomainServer::handleKillNode(SharedNodePointer nodeToKill) { // broadcast out the DomainServerRemovedNode message limitedNodeList->eachMatchingNode([&nodeType](const SharedNodePointer& otherNode) -> bool { // only send the removed node packet to nodes that care about the type of node this was - auto nodeLinkedData = dynamic_cast(otherNode->getLinkedData()); + auto nodeLinkedData = static_cast(otherNode->getLinkedData()); return (nodeLinkedData != nullptr) && nodeLinkedData->getNodeInterestSet().contains(nodeType); }, [&limitedNodeList](const SharedNodePointer& otherNode){ limitedNodeList->sendUnreliablePacket(*removedNodePacket, *otherNode); From db398b7850782bd0942ffd58c2a3889d9f3ef8df Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Jan 2017 13:36:02 -0800 Subject: [PATCH 090/114] check URL host for script whitelist, not startsWith --- libraries/entities/src/EntityTree.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 4796dda671..fdf95d2775 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -958,9 +958,12 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c if (validEditPacket && !_entityScriptSourceWhitelist.isEmpty() && !properties.getScript().isEmpty()) { bool passedWhiteList = false; - auto entityScript = properties.getScript(); + + // grab a URL representation of the entity script so we can check the host for this script + auto entityScriptURL = QUrl::fromUserInput(properties.getScript()); + for (const auto& whiteListedPrefix : _entityScriptSourceWhitelist) { - if (entityScript.startsWith(whiteListedPrefix, Qt::CaseInsensitive)) { + if (entityScriptURL.host().compare(whiteListedPrefix, Qt::CaseInsensitive) == 0) { passedWhiteList = true; break; } From a8118e83ff880f9dd4fc95cb964f9211b1c3b95b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Jan 2017 13:54:43 -0800 Subject: [PATCH 091/114] cleanup debug for safe web entity URLs --- libraries/entities-renderer/src/RenderableWebEntityItem.cpp | 2 ++ libraries/entities/src/WebEntityItem.cpp | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 7f68738bd5..e4d4b222fe 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -251,6 +251,8 @@ void RenderableWebEntityItem::setSourceUrl(const QString& value) { WebEntityItem::setSourceUrl(value); if (_sourceUrl != valueBeforeSuperclassSet && _webSurface) { + qCDebug(entities) << "Changing web entity source URL to " << _sourceUrl; + AbstractViewStateInterface::instance()->postLambdaEvent([this] { _webSurface->getRootItem()->setProperty("url", _sourceUrl); }); diff --git a/libraries/entities/src/WebEntityItem.cpp b/libraries/entities/src/WebEntityItem.cpp index 38ececefa4..5944b5ca3c 100644 --- a/libraries/entities/src/WebEntityItem.cpp +++ b/libraries/entities/src/WebEntityItem.cpp @@ -129,7 +129,6 @@ void WebEntityItem::setSourceUrl(const QString& value) { if (newURL.isValid()) { _sourceUrl = newURL.toDisplayString(); - qCDebug(entities) << "Changed web entity source URL to " << _sourceUrl; } else { qCDebug(entities) << "Clearing web entity source URL since" << value << "cannot be parsed to a valid URL."; } From d108fabd0b9ff64165bcc8d3823546ae9690c458 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 23 Jan 2017 13:56:48 -0800 Subject: [PATCH 092/114] Update the name of the collision shapes used in edit.js properties Update the names to be consistent with what is shown on the add model dialog. --- scripts/system/html/entityProperties.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index 1de59ad135..63131bb155 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -328,13 +328,13 @@
From f6d5a59c8ae2b4a82259a846d7b15f3c537be53b Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 23 Jan 2017 14:18:56 -0800 Subject: [PATCH 093/114] Fix width of edit.js dropdown to accomodate collision options --- scripts/system/html/css/edit-style.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css index 91138e41ec..251d0a2d75 100644 --- a/scripts/system/html/css/edit-style.css +++ b/scripts/system/html/css/edit-style.css @@ -593,7 +593,7 @@ hr { .dropdown dl { font-family: FiraSans-SemiBold; font-size: 15px; - width: 172px; + width: 292px; height: 28px; padding: 0 28px 0 12px; color: #afafaf; @@ -645,7 +645,7 @@ hr { .dropdown li { list-style-type: none; padding: 3px 0 1px 12px; - width: 200px; + width: 320px; height: auto; font-family: FiraSans-SemiBold; font-size: 15px; From a1962e274d2cb6b41dcd51002f897bbbbc3bd670 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 23 Jan 2017 14:35:16 -0800 Subject: [PATCH 094/114] Fix rescale for 0.x values --- scripts/system/edit.js | 2 +- scripts/system/html/js/entityProperties.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index ad04c8b139..91e43ebb9a 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -1556,7 +1556,7 @@ var PropertiesTool = function (opts) { Camera.cameraEntity = selectionManager.selections[0]; } } else if (data.action === "rescaleDimensions") { - var multiplier = data.percentage / 100; + var multiplier = data.percentage / 100.0; if (selectionManager.hasSelection()) { selectionManager.saveProperties(); for (i = 0; i < selectionManager.selections.length; i++) { diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 4fe13196f3..3c155d83ea 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -1392,7 +1392,7 @@ function loaded() { EventBridge.emitWebEvent(JSON.stringify({ type: "action", action: "rescaleDimensions", - percentage: parseInt(elRescaleDimensionsPct.value), + percentage: parseFloat(elRescaleDimensionsPct.value), })); }); elReloadScriptButton.addEventListener("click", function() { From 7362bf16c1d2b1be4e1ec9c5d56523f68afbad72 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Jan 2017 16:33:22 -0800 Subject: [PATCH 095/114] use isParentOf to check script whitelist, clarify description in settings --- domain-server/resources/describe-settings.json | 2 +- libraries/entities/src/EntityTree.cpp | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index c813ffc54c..0084e51239 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -1285,7 +1285,7 @@ { "name": "entityScriptSourceWhitelist", "label": "Entity Scripts Allowed from:", - "help": "The domains that entity scripts are allowed from. A comma separated list of domains that entity scripts are allowed from, if someone attempts to create and entity or edit an entity to have a different domain, it will be rejected. If left blank, any domain is allowed.", + "help": "Comma separated list of URLs (with optional paths) that entity scripts are allowed from. If someone attempts to create and entity or edit an entity to have a different domain, it will be rejected. If left blank, any domain is allowed.", "placeholder": "", "default": "", "advanced": true diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index fdf95d2775..a3f685f95f 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -963,7 +963,17 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c auto entityScriptURL = QUrl::fromUserInput(properties.getScript()); for (const auto& whiteListedPrefix : _entityScriptSourceWhitelist) { - if (entityScriptURL.host().compare(whiteListedPrefix, Qt::CaseInsensitive) == 0) { + auto whiteListURL = QUrl::fromUserInput(whiteListedPrefix); + + if (entityScriptURL.scheme() != whiteListURL.scheme()) { + // isParentOf will be false if the schemes are different, but + } + + qDebug() << "Comparing" << entityScriptURL << "to" << whiteListURL; + qDebug() << whiteListURL.isParentOf(entityScriptURL); + + // check if this script URL matches the whitelist domain and, optionally, is beneath the path + if (whiteListURL.isParentOf(entityScriptURL)) { passedWhiteList = true; break; } From 9229a07f6a3f0ec34647535d3e1a0a93219272c0 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Jan 2017 16:46:59 -0800 Subject: [PATCH 096/114] avoid failing scheme check --- libraries/entities/src/EntityTree.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index a3f685f95f..75fd33bafb 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -965,15 +965,9 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c for (const auto& whiteListedPrefix : _entityScriptSourceWhitelist) { auto whiteListURL = QUrl::fromUserInput(whiteListedPrefix); - if (entityScriptURL.scheme() != whiteListURL.scheme()) { - // isParentOf will be false if the schemes are different, but - } - - qDebug() << "Comparing" << entityScriptURL << "to" << whiteListURL; - qDebug() << whiteListURL.isParentOf(entityScriptURL); - // check if this script URL matches the whitelist domain and, optionally, is beneath the path - if (whiteListURL.isParentOf(entityScriptURL)) { + if (entityScriptURL.host().compare(whiteListURL.host(), Qt::CaseInsensitive) == 0 && + entityScriptURL.path().startsWith(whiteListURL.path(), Qt::CaseInsensitive)) { passedWhiteList = true; break; } From fcaca8930a3a42a43e897076d78a0ea7625e04c4 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 24 Jan 2017 08:31:58 -0800 Subject: [PATCH 097/114] Fix enum name in EntityScriptServer --- assignment-client/src/scripts/EntityScriptServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index b798536ab2..4b7ae2562c 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -41,7 +41,7 @@ EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : ThreadedAssig DependencyManager::set(); DependencyManager::set(); - DependencyManager::set(ENTITY_SERVER_SCRIPT); + DependencyManager::set(ScriptEngine::ENTITY_SERVER_SCRIPT); auto& packetReceiver = DependencyManager::get()->getPacketReceiver(); From e54e35fbbe747652d5ae475988314635e0946894 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 24 Jan 2017 11:49:54 -0800 Subject: [PATCH 098/114] Temporarily remove AvatarList from EntityScriptServer --- assignment-client/src/scripts/EntityScriptServer.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index c1e53dda17..81966d1b2e 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -215,7 +215,6 @@ void EntityScriptServer::resetEntitiesScriptEngine() { auto webSocketServerConstructorValue = newEngine->newFunction(WebSocketServerClass::constructor); newEngine->globalObject().setProperty("WebSocketServer", webSocketServerConstructorValue); - newEngine->registerGlobalObject("AvatarList", DependencyManager::get().data()); newEngine->registerGlobalObject("SoundCache", DependencyManager::get().data()); // connect this script engines printedMessage signal to the global ScriptEngines these various messages From f6a037339f535b602992cd7cecf7927f1a6bed37 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 24 Jan 2017 14:00:55 -0800 Subject: [PATCH 099/114] Fix bad ctor call causing build failure --- assignment-client/src/scripts/EntityScriptServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index 852765581f..18c561efab 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -210,7 +210,7 @@ void EntityScriptServer::selectAudioFormat(const QString& selectedCodecName) { void EntityScriptServer::resetEntitiesScriptEngine() { auto engineName = QString("Entities %1").arg(++_entitiesScriptEngineCount); - auto newEngine = QSharedPointer(new ScriptEngine(NO_SCRIPT, engineName)); + auto newEngine = QSharedPointer(new ScriptEngine(ScriptEngine::ENTITY_SERVER_SCRIPT, NO_SCRIPT, engineName)); auto webSocketServerConstructorValue = newEngine->newFunction(WebSocketServerClass::constructor); newEngine->globalObject().setProperty("WebSocketServer", webSocketServerConstructorValue); From b4d3a2b79fb4d7891353330e395c12f092d536c7 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 24 Jan 2017 16:11:24 -0800 Subject: [PATCH 100/114] Fix member not being set --- libraries/plugins/src/plugins/SteamClientPlugin.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/plugins/src/plugins/SteamClientPlugin.h b/libraries/plugins/src/plugins/SteamClientPlugin.h index f87ebd2e66..95e8d71d92 100644 --- a/libraries/plugins/src/plugins/SteamClientPlugin.h +++ b/libraries/plugins/src/plugins/SteamClientPlugin.h @@ -46,9 +46,9 @@ class SteamScriptingInterface : public QObject { Q_PROPERTY(bool isRunning READ isRunning) public: - SteamScriptingInterface(QObject* parent, SteamClientPlugin* plugin) : QObject(parent) {} + SteamScriptingInterface(QObject* parent, SteamClientPlugin* plugin) : QObject(parent), _plugin(plugin) {} - public slots: +public slots: bool isRunning() const { return _plugin->isRunning(); } void openInviteOverlay() const { _plugin->openInviteOverlay(); } From 808d336fe6071cc4560aa38ef171e874cf3ce665 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 24 Jan 2017 16:17:49 -0800 Subject: [PATCH 101/114] Protect again empty plugin --- libraries/plugins/src/plugins/SteamClientPlugin.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/plugins/src/plugins/SteamClientPlugin.h b/libraries/plugins/src/plugins/SteamClientPlugin.h index 95e8d71d92..bcb15f31de 100644 --- a/libraries/plugins/src/plugins/SteamClientPlugin.h +++ b/libraries/plugins/src/plugins/SteamClientPlugin.h @@ -49,8 +49,8 @@ public: SteamScriptingInterface(QObject* parent, SteamClientPlugin* plugin) : QObject(parent), _plugin(plugin) {} public slots: - bool isRunning() const { return _plugin->isRunning(); } - void openInviteOverlay() const { _plugin->openInviteOverlay(); } + bool isRunning() const { return _plugin && _plugin->isRunning(); } + void openInviteOverlay() const { if (_plugin) { _plugin->openInviteOverlay(); } } private: SteamClientPlugin* _plugin; From 33378ede5ccabcbfc044d3cf6a88c2812b6385b8 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 24 Jan 2017 16:34:57 -0800 Subject: [PATCH 102/114] force full scene send if json parameters changed --- assignment-client/src/octree/OctreeSendThread.cpp | 5 +++-- libraries/entities/src/EntityTreeElement.cpp | 7 ++++--- libraries/octree/src/OctreeQueryNode.cpp | 12 ++++++++++++ libraries/octree/src/OctreeQueryNode.h | 5 +++++ 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 7e88e47da8..afc17d71aa 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -316,8 +316,9 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode* int truePacketsSent = 0; int trueBytesSent = 0; int packetsSentThisInterval = 0; - bool isFullScene = nodeData->getUsesFrustum() && - ((!viewFrustumChanged && nodeData->getViewFrustumJustStoppedChanging()) || nodeData->hasLodChanged()); + bool isFullScene = nodeData->haveJSONParametersChanged() || + (nodeData->getUsesFrustum() + && ((!viewFrustumChanged && nodeData->getViewFrustumJustStoppedChanging()) || nodeData->hasLodChanged())); bool somethingToSend = true; // assume we have something diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 4cd82f223d..51d6d2b270 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -302,14 +302,15 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData includeThisEntity = false; } - if (!jsonFilters.isEmpty()) { + // if this entity has been updated since our last full send and there are json filters, check them + if (includeThisEntity && !jsonFilters.isEmpty()) { // if params include JSON filters, check if this entity matches bool entityMatchesFilters = entity->matchesJSONFilters(jsonFilters); if (entityMatchesFilters) { // we should include this entity unless it has already been excluded - includeThisEntity = includeThisEntity && true; + includeThisEntity = true; // make sure this entity is in the set of entities sent last frame entityNodeData->insertEntitySentLastFrame(entity->getID()); @@ -317,7 +318,7 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData } else { // we might include this entity if it matched in the previous frame if (entityNodeData->sentEntityLastFrame(entity->getID())) { - includeThisEntity = includeThisEntity && true; + includeThisEntity = true; entityNodeData->removeEntitySentLastFrame(entity->getID()); } else { diff --git a/libraries/octree/src/OctreeQueryNode.cpp b/libraries/octree/src/OctreeQueryNode.cpp index fe0c6c2a1f..cffba0bef4 100644 --- a/libraries/octree/src/OctreeQueryNode.cpp +++ b/libraries/octree/src/OctreeQueryNode.cpp @@ -320,3 +320,15 @@ void OctreeQueryNode::parseNackPacket(ReceivedMessage& message) { _nackedSequenceNumbers.enqueue(sequenceNumber); } } + +bool OctreeQueryNode::haveJSONParametersChanged() { + bool parametersChanged = false; + auto currentParameters = getJSONParameters(); + + if (_lastCheckJSONParameters != getJSONParameters()) { + parametersChanged = true; + _lastCheckJSONParameters = currentParameters; + } + + return parametersChanged; +} diff --git a/libraries/octree/src/OctreeQueryNode.h b/libraries/octree/src/OctreeQueryNode.h index 021b293804..10c5598b30 100644 --- a/libraries/octree/src/OctreeQueryNode.h +++ b/libraries/octree/src/OctreeQueryNode.h @@ -100,6 +100,9 @@ public: bool hasNextNackedPacket() const; const NLPacket* getNextNackedPacket(); + // call only from OctreeSendThread for the given node + bool haveJSONParametersChanged(); + private: OctreeQueryNode(const OctreeQueryNode &); OctreeQueryNode& operator= (const OctreeQueryNode&); @@ -143,6 +146,8 @@ private: quint64 _sceneSendStartTime = 0; std::array _lastOctreePayload; + + QJsonObject _lastCheckJSONParameters; }; #endif // hifi_OctreeQueryNode_h From 543d0ce77e36a86183a6786fc725d382aac1c70f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 24 Jan 2017 16:36:44 -0800 Subject: [PATCH 103/114] add a comment about usesFrustum check in EntityTreeElement --- libraries/entities/src/EntityTreeElement.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 51d6d2b270..511aec43c0 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -332,6 +332,8 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData entityTreeElementExtraEncodeData->entities.contains(entity->getEntityItemID()); } + // we only check the bounds against our frustum and LOD if the query has asked us to check against the frustum + // which can sometimes not be the case when JSON filters are sent if (params.usesFrustum && (includeThisEntity || params.recurseEverything)) { // we want to use the maximum possible box for this, so that we don't have to worry about the nuance of From 67a3d97f81c9960f3b03ea1e135fd3a5ef4eb54d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 24 Jan 2017 16:41:20 -0800 Subject: [PATCH 104/114] cleanup includeThisEntity check --- libraries/entities/src/EntityTreeElement.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 511aec43c0..5a7f0d2a87 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -327,9 +327,8 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData } } - if (hadElementExtraData) { - includeThisEntity = includeThisEntity && - entityTreeElementExtraEncodeData->entities.contains(entity->getEntityItemID()); + if (includeThisEntity && hadElementExtraData) { + includeThisEntity = entityTreeElementExtraEncodeData->entities.contains(entity->getEntityItemID()); } // we only check the bounds against our frustum and LOD if the query has asked us to check against the frustum From 69b47dcf50e564766253995dc47a66b4ac345bee Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 24 Jan 2017 16:49:17 -0800 Subject: [PATCH 105/114] use currentParameters instead of getJSONParameters() --- libraries/octree/src/OctreeQueryNode.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/octree/src/OctreeQueryNode.cpp b/libraries/octree/src/OctreeQueryNode.cpp index cffba0bef4..4ebe650f6a 100644 --- a/libraries/octree/src/OctreeQueryNode.cpp +++ b/libraries/octree/src/OctreeQueryNode.cpp @@ -325,7 +325,7 @@ bool OctreeQueryNode::haveJSONParametersChanged() { bool parametersChanged = false; auto currentParameters = getJSONParameters(); - if (_lastCheckJSONParameters != getJSONParameters()) { + if (_lastCheckJSONParameters != currentParameters) { parametersChanged = true; _lastCheckJSONParameters = currentParameters; } From b4400af026bb158a24831514ebb195a41f185645 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 24 Jan 2017 17:04:14 -0800 Subject: [PATCH 106/114] Rename Steam.isRunning to Steam.running --- libraries/plugins/src/plugins/SteamClientPlugin.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/plugins/src/plugins/SteamClientPlugin.h b/libraries/plugins/src/plugins/SteamClientPlugin.h index bcb15f31de..343ed40402 100644 --- a/libraries/plugins/src/plugins/SteamClientPlugin.h +++ b/libraries/plugins/src/plugins/SteamClientPlugin.h @@ -43,7 +43,7 @@ public: class SteamScriptingInterface : public QObject { Q_OBJECT - Q_PROPERTY(bool isRunning READ isRunning) + Q_PROPERTY(bool running READ isRunning) public: SteamScriptingInterface(QObject* parent, SteamClientPlugin* plugin) : QObject(parent), _plugin(plugin) {} From fc42c1bc94e5a6717afa25dacfd64c60bff15e36 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 24 Jan 2017 17:08:13 -0800 Subject: [PATCH 107/114] don't tell ESS about script Agents that won't talk to it --- domain-server/src/DomainServer.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 5a5dd62c40..8a7ff7ab20 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -960,11 +960,14 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif // (1/19/17) Agents only need to connect to Entity Script Servers to perform administrative tasks // related to entity server scripts. Only agents with rez permissions should be doing that, so // if the agent does not have those permissions, we do not want them and the server to incur the - // overhead of connecting to one another. + // overhead of connecting to one another. Additionally we exclude agents that do not care about the + // Entity Script Server and won't attempt to connect to it. + auto otherNodeData = static_cast(otherNode->getLinkedData()); bool shouldNotConnect = (node->getType() == NodeType::Agent && otherNode->getType() == NodeType::EntityScriptServer && !node->getCanRez() && !node->getCanRezTmp()) || (node->getType() == NodeType::EntityScriptServer && otherNode->getType() == NodeType::Agent - && !otherNode->getCanRez() && !otherNode->getCanRezTmp()); + && (!otherNodeData->getNodeInterestSet().contains(NodeType::EntityServer) || + !otherNode->getCanRez() && !otherNode->getCanRezTmp())); if (!shouldNotConnect) { // since we're about to add a node to the packet we start a segment From e511b6e84c84f7534a1e3969e4b06a8ab69ca73f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 24 Jan 2017 17:14:05 -0800 Subject: [PATCH 108/114] cleanup connect check in DomainServer --- domain-server/src/DomainServer.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 8a7ff7ab20..8e44922424 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -963,11 +963,17 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif // overhead of connecting to one another. Additionally we exclude agents that do not care about the // Entity Script Server and won't attempt to connect to it. auto otherNodeData = static_cast(otherNode->getLinkedData()); - bool shouldNotConnect = (node->getType() == NodeType::Agent && otherNode->getType() == NodeType::EntityScriptServer - && !node->getCanRez() && !node->getCanRezTmp()) - || (node->getType() == NodeType::EntityScriptServer && otherNode->getType() == NodeType::Agent - && (!otherNodeData->getNodeInterestSet().contains(NodeType::EntityServer) || - !otherNode->getCanRez() && !otherNode->getCanRezTmp())); + + bool isAgentWithoutRights = node->getType() == NodeType::Agent + && otherNode->getType() == NodeType::EntityScriptServer + && !node->getCanRez() && !node->getCanRezTmp(); + + bool isScriptServerForIneffectiveAgent = + (node->getType() == NodeType::EntityScriptServer && otherNode->getType() == NodeType::Agent) + && (!otherNodeData->getNodeInterestSet().contains(NodeType::EntityServer) + || (!otherNode->getCanRez() && !otherNode->getCanRezTmp())); + + bool shouldNotConnect = isAgentWithoutRights || isScriptServerForIneffectiveAgent; if (!shouldNotConnect) { // since we're about to add a node to the packet we start a segment From 586c3512a77f6cc2739d898ad3ac32a9afc946a9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 24 Jan 2017 17:35:45 -0800 Subject: [PATCH 109/114] remove useless additional includeThisEntity sets --- libraries/entities/src/EntityTreeElement.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 5a7f0d2a87..525c1ec65f 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -309,16 +309,12 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData bool entityMatchesFilters = entity->matchesJSONFilters(jsonFilters); if (entityMatchesFilters) { - // we should include this entity unless it has already been excluded - includeThisEntity = true; - // make sure this entity is in the set of entities sent last frame entityNodeData->insertEntitySentLastFrame(entity->getID()); } else { // we might include this entity if it matched in the previous frame if (entityNodeData->sentEntityLastFrame(entity->getID())) { - includeThisEntity = true; entityNodeData->removeEntitySentLastFrame(entity->getID()); } else { From 9b8cbba53f33cccc634ba15f6b09e4c039d8fe5a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 24 Jan 2017 18:22:22 -0800 Subject: [PATCH 110/114] add isInInterestSet to DomainServer for extra checks --- domain-server/src/DomainServer.cpp | 87 +++++++++++++++++------------- domain-server/src/DomainServer.h | 2 + 2 files changed, 52 insertions(+), 37 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 8e44922424..1424091fdb 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -855,6 +855,44 @@ void DomainServer::processListRequestPacket(QSharedPointer mess sendDomainListToNode(sendingNode, message->getSenderSockAddr()); } +bool DomainServer::isInInterestSet(const SharedNodePointer& nodeA, const SharedNodePointer& nodeB) { + auto nodeAData = static_cast(nodeA->getLinkedData()); + auto nodeBData = static_cast(nodeB->getLinkedData()); + + // if we have no linked data for node A then B can't possibly be in the interest set + if (!nodeAData) { + return false; + } + + // first check if the general interest set A contains the type for B + if (nodeAData->getNodeInterestSet().contains(nodeB->getType())) { + // given that there is a match in the general interest set, do any special checks + + // (1/19/17) Agents only need to connect to Entity Script Servers to perform administrative tasks + // related to entity server scripts. Only agents with rez permissions should be doing that, so + // if the agent does not have those permissions, we do not want them and the server to incur the + // overhead of connecting to one another. Additionally we exclude agents that do not care about the + // Entity Script Server and won't attempt to connect to it. + + bool isAgentWithoutRights = nodeA->getType() == NodeType::Agent + && nodeB->getType() == NodeType::EntityScriptServer + && !nodeA->getCanRez() && !nodeA->getCanRezTmp(); + + if (isAgentWithoutRights) { + return false; + } + + bool isScriptServerForIneffectiveAgent = + (nodeA->getType() == NodeType::EntityScriptServer && nodeB->getType() == NodeType::Agent) + && ((nodeBData && !nodeBData->getNodeInterestSet().contains(NodeType::EntityScriptServer)) + || (!nodeB->getCanRez() && !nodeB->getCanRezTmp())); + + return !isScriptServerForIneffectiveAgent; + } else { + return false; + } +} + unsigned int DomainServer::countConnectedUsers() { unsigned int result = 0; auto nodeList = DependencyManager::get(); @@ -954,40 +992,18 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif if (nodeData->isAuthenticated()) { // if this authenticated node has any interest types, send back those nodes as well limitedNodeList->eachNode([&](const SharedNodePointer& otherNode) { - if (otherNode->getUUID() != node->getUUID() - && nodeInterestSet.contains(otherNode->getType())) { + if (otherNode->getUUID() != node->getUUID() && isInInterestSet(node, otherNode)) { + // since we're about to add a node to the packet we start a segment + domainListPackets->startSegment(); - // (1/19/17) Agents only need to connect to Entity Script Servers to perform administrative tasks - // related to entity server scripts. Only agents with rez permissions should be doing that, so - // if the agent does not have those permissions, we do not want them and the server to incur the - // overhead of connecting to one another. Additionally we exclude agents that do not care about the - // Entity Script Server and won't attempt to connect to it. - auto otherNodeData = static_cast(otherNode->getLinkedData()); + // don't send avatar nodes to other avatars, that will come from avatar mixer + domainListStream << *otherNode.data(); - bool isAgentWithoutRights = node->getType() == NodeType::Agent - && otherNode->getType() == NodeType::EntityScriptServer - && !node->getCanRez() && !node->getCanRezTmp(); + // pack the secret that these two nodes will use to communicate with each other + domainListStream << connectionSecretForNodes(node, otherNode); - bool isScriptServerForIneffectiveAgent = - (node->getType() == NodeType::EntityScriptServer && otherNode->getType() == NodeType::Agent) - && (!otherNodeData->getNodeInterestSet().contains(NodeType::EntityServer) - || (!otherNode->getCanRez() && !otherNode->getCanRezTmp())); - - bool shouldNotConnect = isAgentWithoutRights || isScriptServerForIneffectiveAgent; - - if (!shouldNotConnect) { - // since we're about to add a node to the packet we start a segment - domainListPackets->startSegment(); - - // don't send avatar nodes to other avatars, that will come from avatar mixer - domainListStream << *otherNode.data(); - - // pack the secret that these two nodes will use to communicate with each other - domainListStream << connectionSecretForNodes(node, otherNode); - - // we've added the node we wanted so end the segment now - domainListPackets->endSegment(); - } + // we've added the node we wanted so end the segment now + domainListPackets->endSegment(); } }); } @@ -1038,8 +1054,7 @@ void DomainServer::broadcastNewNode(const SharedNodePointer& addedNode) { [&](const SharedNodePointer& node)->bool { if (node->getLinkedData() && node->getActiveSocket() && node != addedNode) { // is the added Node in this node's interest list? - DomainServerNodeData* nodeData = dynamic_cast(node->getLinkedData()); - return nodeData->getNodeInterestSet().contains(addedNode->getType()); + return isInInterestSet(node, addedNode); } else { return false; } @@ -2389,7 +2404,6 @@ void DomainServer::processNodeDisconnectRequestPacket(QSharedPointergetType(); auto limitedNodeList = DependencyManager::get(); const QUuid& nodeUUID = nodeToKill->getUUID(); @@ -2401,10 +2415,9 @@ void DomainServer::handleKillNode(SharedNodePointer nodeToKill) { removedNodePacket->write(nodeUUID.toRfc4122()); // broadcast out the DomainServerRemovedNode message - limitedNodeList->eachMatchingNode([&nodeType](const SharedNodePointer& otherNode) -> bool { + limitedNodeList->eachMatchingNode([this, &nodeToKill](const SharedNodePointer& otherNode) -> bool { // only send the removed node packet to nodes that care about the type of node this was - auto nodeLinkedData = dynamic_cast(otherNode->getLinkedData()); - return (nodeLinkedData != nullptr) && nodeLinkedData->getNodeInterestSet().contains(nodeType); + return isInInterestSet(otherNode, nodeToKill); }, [&limitedNodeList](const SharedNodePointer& otherNode){ limitedNodeList->sendUnreliablePacket(*removedNodePacket, *otherNode); }); diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 73135695eb..4c5c42acee 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -132,6 +132,8 @@ private: void sendDomainListToNode(const SharedNodePointer& node, const HifiSockAddr& senderSockAddr); + bool isInInterestSet(const SharedNodePointer& nodeA, const SharedNodePointer& nodeB); + QUuid connectionSecretForNodes(const SharedNodePointer& nodeA, const SharedNodePointer& nodeB); void broadcastNewNode(const SharedNodePointer& node); From 9cacde2416e8740f0551ebf76aa3506c4e2b05f2 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 24 Jan 2017 18:36:27 -0800 Subject: [PATCH 111/114] Fix wrong status when removing script --- assignment-client/src/scripts/EntityScriptServer.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index 18c561efab..7f4593910e 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -286,9 +286,11 @@ void EntityScriptServer::checkAndCallPreload(const EntityItemID& entityID, const bool notRunning = !_entitiesScriptEngine->getEntityScriptDetails(entityID, details); if (entity && (reload || notRunning || details.scriptText != entity->getServerScripts())) { QString scriptUrl = entity->getServerScripts(); - scriptUrl = ResourceManager::normalizeURL(scriptUrl); - qDebug() << "Loading entity server script" << scriptUrl << "for" << entityID; - ScriptEngine::loadEntityScript(_entitiesScriptEngine, entityID, scriptUrl, reload); + if (!scriptUrl.isEmpty()) { + scriptUrl = ResourceManager::normalizeURL(scriptUrl); + qDebug() << "Loading entity server script" << scriptUrl << "for" << entityID; + ScriptEngine::loadEntityScript(_entitiesScriptEngine, entityID, scriptUrl, reload); + } } } } From 2bb7a7a4a6e93efabd2e27f6c9e5e138765613f0 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 25 Jan 2017 09:32:25 -0800 Subject: [PATCH 112/114] Remove entity server script status log spam from edit.js --- scripts/system/edit.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 29396614a6..62ec181faf 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -1396,9 +1396,7 @@ var ServerScriptStatusMonitor = function(entityID, statusCallback) { self.sendRequestTimerID = null; var onStatusReceived = function(success, isRunning, status, errorInfo) { - print("Got script status:", success, isRunning, status, errorInfo); if (self.active) { - print("Requesting status of script"); statusCallback({ statusRetrieved: success, isRunning: isRunning, From f1b4f79ad9040dda1774ab54d9a7fd18c6a75e75 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 25 Jan 2017 11:28:02 -0800 Subject: [PATCH 113/114] a simple hack to accept newer server scripts --- libraries/entities/src/EntityItem.cpp | 17 +++++++++++++++++ libraries/entities/src/EntityItem.h | 5 ++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 0b2e7fd5ca..8b2763fec8 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -780,7 +780,24 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY(PROP_LIFETIME, float, updateLifetime); READ_ENTITY_PROPERTY(PROP_SCRIPT, QString, setScript); READ_ENTITY_PROPERTY(PROP_SCRIPT_TIMESTAMP, quint64, setScriptTimestamp); + + bool previousOverwriteLocalDataValue = overwriteLocalData; + + if (!overwriteLocalData) { + // We've decided not to read the data in this update because we have a newer local state of the entity. + // In order to work around a bug stopping server script changes from being received by an entity script server + // running a script that continously updates an entity, we force the overwriting of the server scripts + // if we believe this update might have a newer version than the one we have locally. + + if (_lastEditedFromRemote > _serverScriptsChangedTimestamp) { + overwriteLocalData = true; + } + } + READ_ENTITY_PROPERTY(PROP_SERVER_SCRIPTS, QString, setServerScripts); + + overwriteLocalData = previousOverwriteLocalDataValue; + READ_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, glm::vec3, updateRegistrationPoint); READ_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, float, updateAngularDamping); diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 2fb91d0d77..718a399a39 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -261,7 +261,8 @@ public: void setScriptTimestamp(const quint64 value) { _scriptTimestamp = value; } QString getServerScripts() const { return _serverScripts; } - void setServerScripts(const QString& serverScripts) { _serverScripts = serverScripts; } + void setServerScripts(const QString& serverScripts) + { _serverScripts = serverScripts; _serverScriptsChangedTimestamp = usecTimestampNow(); } const QString& getCollisionSoundURL() const { return _collisionSoundURL; } void setCollisionSoundURL(const QString& value); @@ -515,7 +516,9 @@ protected: QString _script; /// the value of the script property QString _loadedScript; /// the value of _script when the last preload signal was sent quint64 _scriptTimestamp{ ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP }; /// the script loaded property used for forced reload + QString _serverScripts; + quint64 _serverScriptsChangedTimestamp; /// keep track of time when _serverScripts property was last changed /// the value of _scriptTimestamp when the last preload signal was sent // NOTE: on construction we want this to be different from _scriptTimestamp so we intentionally bump it From 304618f51dc877103f552c1e8503517b7870f354 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 25 Jan 2017 12:39:21 -0800 Subject: [PATCH 114/114] cleanup comment and scoping for server script URL changes --- libraries/entities/src/EntityItem.cpp | 21 ++++++++------------- libraries/entities/src/EntityItem.h | 3 ++- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 8b2763fec8..28d07672a0 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -781,23 +781,18 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY(PROP_SCRIPT, QString, setScript); READ_ENTITY_PROPERTY(PROP_SCRIPT_TIMESTAMP, quint64, setScriptTimestamp); - bool previousOverwriteLocalDataValue = overwriteLocalData; + { + // We use this scope to work around an issue stopping server script changes + // from being received by an entity script server running a script that continously updates an entity. - if (!overwriteLocalData) { - // We've decided not to read the data in this update because we have a newer local state of the entity. - // In order to work around a bug stopping server script changes from being received by an entity script server - // running a script that continously updates an entity, we force the overwriting of the server scripts - // if we believe this update might have a newer version than the one we have locally. + // Basically, we'll allow recent changes to the server scripts even if there are local changes to other properties + // that have been made more recently. - if (_lastEditedFromRemote > _serverScriptsChangedTimestamp) { - overwriteLocalData = true; - } + bool overwriteLocalData = !ignoreServerPacket || (lastEditedFromBufferAdjusted > _serverScriptsChangedTimestamp); + + READ_ENTITY_PROPERTY(PROP_SERVER_SCRIPTS, QString, setServerScripts); } - READ_ENTITY_PROPERTY(PROP_SERVER_SCRIPTS, QString, setServerScripts); - - overwriteLocalData = previousOverwriteLocalDataValue; - READ_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, glm::vec3, updateRegistrationPoint); READ_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, float, updateAngularDamping); diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 718a399a39..b0389cf99f 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -518,7 +518,8 @@ protected: quint64 _scriptTimestamp{ ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP }; /// the script loaded property used for forced reload QString _serverScripts; - quint64 _serverScriptsChangedTimestamp; /// keep track of time when _serverScripts property was last changed + /// keep track of time when _serverScripts property was last changed + quint64 _serverScriptsChangedTimestamp { ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP }; /// the value of _scriptTimestamp when the last preload signal was sent // NOTE: on construction we want this to be different from _scriptTimestamp so we intentionally bump it