History

resolve conflicts on merge with uptream/master

Stephen Birarda committed 11 years ago

Commit 821c16c2 parents 684d466 4e2cbb399 files · +2638 −5187Browse files

Showing the changes to libraries/script-engine/src/ScriptEngine.cpp (1 of 99 files). Show all

Unified · Split

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