Showing the changes to libraries/script-engine/src/ScriptEngine.cpp (1 of 99 files). Show all
Unified · Split
| @@ -121,7 +121,7 @@ bool ScriptEngine::_doneRunningThisScript = false; · 120 unmodified lines | ||
| 121 | 121 | void ScriptEngine::stopAllScripts(QObject* application) { |
| 122 | 122 | _allScriptsMutex.lock(); |
| 123 | 123 | _stoppingAllScripts = true; |
| 124 | − | |
| 124 | + | |
| 125 | 125 | QMutableSetIterator<ScriptEngine*> i(_allKnownScriptEngines); |
| 126 | 126 | while (i.hasNext()) { |
| 127 | 127 | ScriptEngine* scriptEngine = i.next(); |
| @@ -130,14 +130,14 @@ void ScriptEngine::stopAllScripts(QObject* application) { · 2 unmodified lines | ||
| 130 | 130 | |
| 131 | 131 | // NOTE: typically all script engines are running. But there's at least one known exception to this, the |
| 132 | 132 | // "entities sandbox" which is only used to evaluate entities scripts to test their validity before using |
| 133 | − // them. We don't need to stop scripts that aren't running. | |
| 133 | + // them. We don't need to stop scripts that aren't running. | |
| 134 | 134 | if (scriptEngine->isRunning()) { |
| 135 | − | |
| 135 | + | |
| 136 | 136 | // If the script is running, but still evaluating then we need to wait for its evaluation step to |
| 137 | 137 | // complete. After that we can handle the stop process appropriately |
| 138 | 138 | if (scriptEngine->evaluatePending()) { |
| 139 | 139 | while (scriptEngine->evaluatePending()) { |
| 140 | − | |
| 140 | + | |
| 141 | 141 | // This event loop allows any started, but not yet finished evaluate() calls to complete |
| 142 | 142 | // we need to let these complete so that we can be guaranteed that the script engine isn't |
| 143 | 143 | // in a partially setup state, which can confuse our shutdown unwinding. |
| @@ -147,11 +147,11 @@ void ScriptEngine::stopAllScripts(QObject* application) { · 3 unmodified lines | ||
| 147 | 147 | } |
| 148 | 148 | } |
| 149 | 149 | |
| 150 | − // We disconnect any script engine signals from the application because we don't want to do any | |
| 150 | + // We disconnect any script engine signals from the application because we don't want to do any | |
| 151 | 151 | // extra stopScript/loadScript processing that the Application normally does when scripts start |
| 152 | 152 | // and stop. We can safely short circuit this because we know we're in the "quitting" process |
| 153 | 153 | scriptEngine->disconnect(application); |
| 154 | − | |
| 154 | + | |
| 155 | 155 | // Calling stop on the script engine will set it's internal _isFinished state to true, and result |
| 156 | 156 | // in the ScriptEngine gracefully ending it's run() method. |
| 157 | 157 | scriptEngine->stop(); |
| @@ -160,7 +160,7 @@ void ScriptEngine::stopAllScripts(QObject* application) { · 2 unmodified lines | ||
| 160 | 160 | // want any of the scripts final "scriptEnding()" or pending "update()" methods from accessing |
| 161 | 161 | // any application state after we leave this stopAllScripts() method |
| 162 | 162 | scriptEngine->waitTillDoneRunning(); |
| 163 | − | |
| 163 | + | |
| 164 | 164 | // If the script is stopped, we can remove it from our set |
| 165 | 165 | i.remove(); |
| 166 | 166 | } |
| @@ -177,26 +177,26 @@ void ScriptEngine::waitTillDoneRunning() { · 10 unmodified lines | ||
| 177 | 177 | if (_isRunning) { |
| 178 | 178 | |
| 179 | 179 | _doneRunningThisScript = false; // NOTE: this is static, we serialize our waiting for scripts to finish |
| 180 | − | |
| 180 | + | |
| 181 | 181 | // NOTE: waitTillDoneRunning() will be called on the main Application thread, inside of stopAllScripts() |
| 182 | − // we want the application thread to continue to process events, because the scripts will likely need to | |
| 182 | + // we want the application thread to continue to process events, because the scripts will likely need to | |
| 183 | 183 | // marshall messages across to the main thread. For example if they access Settings or Meny in any of their |
| 184 | 184 | // shutdown code. |
| 185 | 185 | while (!_doneRunningThisScript) { |
| 186 | − | |
| 186 | + | |
| 187 | 187 | // process events for the main application thread, allowing invokeMethod calls to pass between threads |
| 188 | 188 | QCoreApplication::processEvents(); |
| 189 | 189 | } |
| 190 | 190 | } |
| 191 | 191 | } |
| 192 | 192 | |
| 193 | −QString ScriptEngine::getFilename() const { | |
| 193 | +QString ScriptEngine::getFilename() const { | |
| 194 | 194 | QStringList fileNameParts = _fileNameString.split("/"); |
| 195 | 195 | QString lastPart; |
| 196 | 196 | if (!fileNameParts.isEmpty()) { |
| 197 | 197 | lastPart = fileNameParts.last(); |
| 198 | 198 | } |
| 199 | − return lastPart; | |
| 199 | + return lastPart; | |
| 200 | 200 | } |
| 201 | 201 | |
| 202 | 202 | |
| @@ -259,15 +259,15 @@ void ScriptEngine::loadURL(const QUrl& scriptURL, bool reload) { · 56 unmodified lines | ||
| 259 | 259 | |
| 260 | 260 | _fileNameString = scriptURL.toString(); |
| 261 | 261 | _isReloading = reload; |
| 262 | − | |
| 262 | + | |
| 263 | 263 | QUrl url(scriptURL); |
| 264 | − | |
| 264 | + | |
| 265 | 265 | // if the scheme length is one or lower, maybe they typed in a file, let's try |
| 266 | 266 | const int WINDOWS_DRIVE_LETTER_SIZE = 1; |
| 267 | 267 | if (url.scheme().size() <= WINDOWS_DRIVE_LETTER_SIZE) { |
| 268 | 268 | url = QUrl::fromLocalFile(_fileNameString); |
| 269 | 269 | } |
| 270 | − | |
| 270 | + | |
| 271 | 271 | // ok, let's see if it's valid... and if so, load it |
| 272 | 272 | if (url.isValid()) { |
| 273 | 273 | if (url.scheme() == "file") { |
| @@ -304,7 +304,7 @@ void ScriptEngine::init() { · 30 unmodified lines | ||
| 304 | 304 | if (_isInitialized) { |
| 305 | 305 | return; // only initialize once |
| 306 | 306 | } |
| 307 | − | |
| 307 | + | |
| 308 | 308 | _isInitialized = true; |
| 309 | 309 | |
| 310 | 310 | auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>(); |
| @@ -318,7 +318,7 @@ void ScriptEngine::init() { · 7 unmodified lines | ||
| 318 | 318 | registerAnimationTypes(this); |
| 319 | 319 | registerAvatarTypes(this); |
| 320 | 320 | registerAudioMetaTypes(this); |
| 321 | − | |
| 321 | + | |
| 322 | 322 | if (_controllerScriptingInterface) { |
| 323 | 323 | _controllerScriptingInterface->registerControllerTypes(this); |
| 324 | 324 | } |
| @@ -341,7 +341,7 @@ void ScriptEngine::init() { · 16 unmodified lines | ||
| 341 | 341 | |
| 342 | 342 | QScriptValue audioEffectOptionsConstructorValue = newFunction(AudioEffectOptions::constructor); |
| 343 | 343 | globalObject().setProperty("AudioEffectOptions", audioEffectOptionsConstructorValue); |
| 344 | − | |
| 344 | + | |
| 345 | 345 | qScriptRegisterMetaType(this, injectorToScriptValue, injectorFromScriptValue); |
| 346 | 346 | qScriptRegisterMetaType(this, inputControllerToScriptValue, inputControllerFromScriptValue); |
| 347 | 347 | qScriptRegisterMetaType(this, avatarDataToScriptValue, avatarDataFromScriptValue); |
| @@ -436,7 +436,7 @@ void ScriptEngine::addEventHandler(const EntityItemID& entityID, const QString& · 88 unmodified lines | ||
| 436 | 436 | [=](const EntityItemID& entityID) { |
| 437 | 437 | _registeredHandlers.remove(entityID); |
| 438 | 438 | }); |
| 439 | − | |
| 439 | + | |
| 440 | 440 | // Two common cases of event handler, differing only in argument signature. |
| 441 | 441 | auto makeSingleEntityHandler = [=](const QString& eventName) -> std::function<void(const EntityItemID&)> { |
| 442 | 442 | return [=](const EntityItemID& entityItemID) -> void { |
| @@ -454,19 +454,19 @@ void ScriptEngine::addEventHandler(const EntityItemID& entityID, const QString& · 11 unmodified lines | ||
| 454 | 454 | }; |
| 455 | 455 | connect(entities.data(), &EntityScriptingInterface::enterEntity, this, makeSingleEntityHandler("enterEntity")); |
| 456 | 456 | connect(entities.data(), &EntityScriptingInterface::leaveEntity, this, makeSingleEntityHandler("leaveEntity")); |
| 457 | − | |
| 457 | + | |
| 458 | 458 | connect(entities.data(), &EntityScriptingInterface::mousePressOnEntity, this, makeMouseHandler("mousePressOnEntity")); |
| 459 | 459 | connect(entities.data(), &EntityScriptingInterface::mouseMoveOnEntity, this, makeMouseHandler("mouseMoveOnEntity")); |
| 460 | 460 | connect(entities.data(), &EntityScriptingInterface::mouseReleaseOnEntity, this, makeMouseHandler("mouseReleaseOnEntity")); |
| 461 | − | |
| 461 | + | |
| 462 | 462 | connect(entities.data(), &EntityScriptingInterface::clickDownOnEntity, this, makeMouseHandler("clickDownOnEntity")); |
| 463 | 463 | connect(entities.data(), &EntityScriptingInterface::holdingClickOnEntity, this, makeMouseHandler("holdingClickOnEntity")); |
| 464 | 464 | connect(entities.data(), &EntityScriptingInterface::clickReleaseOnEntity, this, makeMouseHandler("clickReleaseOnEntity")); |
| 465 | − | |
| 465 | + | |
| 466 | 466 | connect(entities.data(), &EntityScriptingInterface::hoverEnterEntity, this, makeMouseHandler("hoverEnterEntity")); |
| 467 | 467 | connect(entities.data(), &EntityScriptingInterface::hoverOverEntity, this, makeMouseHandler("hoverOverEntity")); |
| 468 | 468 | connect(entities.data(), &EntityScriptingInterface::hoverLeaveEntity, this, makeMouseHandler("hoverLeaveEntity")); |
| 469 | − | |
| 469 | + | |
| 470 | 470 | connect(entities.data(), &EntityScriptingInterface::collisionWithEntity, this, |
| 471 | 471 | [=](const EntityItemID& idA, const EntityItemID& idB, const Collision& collision) { |
| 472 | 472 | generalHandler(idA, "collisionWithEntity", [=]() { |
| @@ -587,10 +587,12 @@ void ScriptEngine::run() { · 114 unmodified lines | ||
| 587 | 587 | / (1000 * 1000)) + 0.5); |
| 588 | 588 | const int SCRIPT_AUDIO_BUFFER_BYTES = SCRIPT_AUDIO_BUFFER_SAMPLES * sizeof(int16_t); |
| 589 | 589 | |
| 590 | − QByteArray avatarPacket = nodeList->byteArrayWithPopulatedHeader(PacketTypeAvatarData); | |
| 591 | − avatarPacket.append(_avatarData->toByteArray()); | |
| 590 | + QByteArray avatarByteArray = _avatarData->toByteArray(); | |
| 591 | + auto avatarPacket = NLPacket::create(PacketType::AvatarData, avatarByteArray.size()); | |
| 592 | + | |
| 593 | + avatarPacket->write(avatarByteArray); | |
| 592 | 594 | |
| 593 | − nodeList->broadcastToNodes(avatarPacket, NodeSet() << NodeType::AvatarMixer); | |
| 595 | + nodeList->broadcastToNodes(std::move(avatarPacket), NodeSet() << NodeType::AvatarMixer); | |
| 594 | 596 | |
| 595 | 597 | if (_isListeningToAudioStream || _avatarSound) { |
| 596 | 598 | // if we have an avatar audio stream then send it out to our audio-mixer |
| @@ -627,16 +629,13 @@ void ScriptEngine::run() { · 30 unmodified lines | ||
| 627 | 629 | _numAvatarSoundSentBytes = 0; |
| 628 | 630 | } |
| 629 | 631 | } |
| 630 | − | |
| 631 | − QByteArray audioPacket = nodeList->byteArrayWithPopulatedHeader(silentFrame | |
| 632 | − ? PacketTypeSilentAudioFrame | |
| 633 | − : PacketTypeMicrophoneAudioNoEcho); | |
| 634 | 632 | |
| 635 | − QDataStream packetStream(&audioPacket, QIODevice::Append); | |
| 633 | + auto audioPacket = NLPacket::create(silentFrame | |
| 634 | + ? PacketType::SilentAudioFrame | |
| 635 | + : PacketType::MicrophoneAudioNoEcho); | |
| 636 | 636 | |
| 637 | − // pack a placeholder value for sequence number for now, will be packed when destination node is known | |
| 638 | − int numPreSequenceNumberBytes = audioPacket.size(); | |
| 639 | − packetStream << (quint16) 0; | |
| 637 | + // seek past the sequence number, will be packed when destination node is known | |
| 638 | + audioPacket->seek(sizeof(quint16)); | |
| 640 | 639 | |
| 641 | 640 | if (silentFrame) { |
| 642 | 641 | if (!_isListeningToAudioStream) { |
| @@ -645,37 +644,38 @@ void ScriptEngine::run() { · 2 unmodified lines | ||
| 645 | 644 | } |
| 646 | 645 | |
| 647 | 646 | // write the number of silent samples so the audio-mixer can uphold timing |
| 648 | − packetStream.writeRawData(reinterpret_cast<const char*>(&SCRIPT_AUDIO_BUFFER_SAMPLES), sizeof(int16_t)); | |
| 647 | + audioPacket->writePrimitive(SCRIPT_AUDIO_BUFFER_SAMPLES); | |
| 649 | 648 | |
| 650 | 649 | // use the orientation and position of this avatar for the source of this audio |
| 651 | − packetStream.writeRawData(reinterpret_cast<const char*>(&_avatarData->getPosition()), sizeof(glm::vec3)); | |
| 650 | + audioPacket->writePrimitive(_avatarData->getPosition()); | |
| 652 | 651 | glm::quat headOrientation = _avatarData->getHeadOrientation(); |
| 653 | − packetStream.writeRawData(reinterpret_cast<const char*>(&headOrientation), sizeof(glm::quat)); | |
| 652 | + audioPacket->writePrimitive(headOrientation); | |
| 654 | 653 | |
| 655 | 654 | } else if (nextSoundOutput) { |
| 656 | 655 | // assume scripted avatar audio is mono and set channel flag to zero |
| 657 | − packetStream << (quint8)0; | |
| 656 | + audioPacket->writePrimitive((quint8) 0); | |
| 658 | 657 | |
| 659 | 658 | // use the orientation and position of this avatar for the source of this audio |
| 660 | − packetStream.writeRawData(reinterpret_cast<const char*>(&_avatarData->getPosition()), sizeof(glm::vec3)); | |
| 659 | + audioPacket->writePrimitive(_avatarData->getPosition()); | |
| 661 | 660 | glm::quat headOrientation = _avatarData->getHeadOrientation(); |
| 662 | − packetStream.writeRawData(reinterpret_cast<const char*>(&headOrientation), sizeof(glm::quat)); | |
| 661 | + audioPacket->writePrimitive(headOrientation); | |
| 663 | 662 | |
| 664 | 663 | // write the raw audio data |
| 665 | − packetStream.writeRawData(reinterpret_cast<const char*>(nextSoundOutput), numAvailableSamples * sizeof(int16_t)); | |
| 664 | + audioPacket->write(reinterpret_cast<const char*>(nextSoundOutput), numAvailableSamples * sizeof(int16_t)); | |
| 666 | 665 | } |
| 667 | − | |
| 666 | + | |
| 668 | 667 | // write audio packet to AudioMixer nodes |
| 669 | 668 | auto nodeList = DependencyManager::get<NodeList>(); |
| 670 | − nodeList->eachNode([this, &nodeList, &audioPacket, &numPreSequenceNumberBytes](const SharedNodePointer& node){ | |
| 669 | + nodeList->eachNode([this, &nodeList, &audioPacket](const SharedNodePointer& node){ | |
| 671 | 670 | // only send to nodes of type AudioMixer |
| 672 | 671 | if (node->getType() == NodeType::AudioMixer) { |
| 673 | 672 | // pack sequence number |
| 674 | 673 | quint16 sequence = _outgoingScriptAudioSequenceNumbers[node->getUUID()]++; |
| 675 | − memcpy(audioPacket.data() + numPreSequenceNumberBytes, &sequence, sizeof(quint16)); | |
| 676 | − | |
| 674 | + audioPacket->seek(0); | |
| 675 | + audioPacket->writePrimitive(sequence); | |
| 676 | + | |
| 677 | 677 | // send audio packet |
| 678 | − nodeList->writeDatagram(audioPacket, node); | |
| 678 | + nodeList->sendUnreliablePacket(*audioPacket, node); | |
| 679 | 679 | } |
| 680 | 680 | }); |
| 681 | 681 | } |
| @@ -695,7 +695,7 @@ void ScriptEngine::run() { · 13 unmodified lines | ||
| 695 | 695 | emit update(deltaTime); |
| 696 | 696 | } |
| 697 | 697 | lastUpdate = now; |
| 698 | − | |
| 698 | + | |
| 699 | 699 | } |
| 700 | 700 | |
| 701 | 701 | stopAllTimers(); // make sure all our timers are stopped if the script is ending |
| @@ -756,13 +756,13 @@ void ScriptEngine::stop() { · 54 unmodified lines | ||
| 756 | 756 | void ScriptEngine::timerFired() { |
| 757 | 757 | QTimer* callingTimer = reinterpret_cast<QTimer*>(sender()); |
| 758 | 758 | QScriptValue timerFunction = _timerFunctionMap.value(callingTimer); |
| 759 | − | |
| 759 | + | |
| 760 | 760 | if (!callingTimer->isActive()) { |
| 761 | 761 | // this timer is done, we can kill it |
| 762 | 762 | _timerFunctionMap.remove(callingTimer); |
| 763 | 763 | delete callingTimer; |
| 764 | 764 | } |
| 765 | − | |
| 765 | + | |
| 766 | 766 | // call the associated JS function, if it exists |
| 767 | 767 | if (timerFunction.isValid()) { |
| 768 | 768 | timerFunction.call(); |
| @@ -856,7 +856,7 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac · 87 unmodified lines | ||
| 856 | 856 | } |
| 857 | 857 | |
| 858 | 858 | BatchLoader* loader = new BatchLoader(urls); |
| 859 | − | |
| 859 | + | |
| 860 | 860 | auto evaluateScripts = [=](const QMap<QUrl, QString>& data) { |
| 861 | 861 | for (QUrl url : urls) { |
| 862 | 862 | QString contents = data[url]; |
| @@ -890,7 +890,7 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac · 27 unmodified lines | ||
| 890 | 890 | |
| 891 | 891 | void ScriptEngine::include(const QString& includeFile, QScriptValue callback) { |
| 892 | 892 | if (_stoppingAllScripts) { |
| 893 | − qCDebug(scriptengine) << "Script.include() while shutting down is ignored... " | |
| 893 | + qCDebug(scriptengine) << "Script.include() while shutting down is ignored... " | |
| 894 | 894 | << "includeFile:" << includeFile << "parent script:" << getFilename(); |
| 895 | 895 | return; // bail early |
| 896 | 896 | } |