qint64 now = usecTimestampNow(); float deltaTime = (float) (now - lastUpdate) / (float) USECS_PER_SECOND; if (hasUncaughtException()) { int line = uncaughtExceptionLineNumber(); qDebug() << "Uncaught exception at (" << _fileNameString << ") line" << line << ":" << uncaughtException().toString(); emit errorMessage("Uncaught exception at (" + _fileNameString + ") line" + QString::number(line) + ":" + uncaughtException().toString()); clearExceptions(); } emit update(deltaTime); lastUpdate = now; } emit scriptEnding(); // kill the avatar identity timer delete _avatarIdentityTimer; if (_voxelsScriptingInterface.getVoxelPacketSender()->serversExist()) { // release the queue of edit voxel messages. _voxelsScriptingInterface.getVoxelPacketSender()->releaseQueuedMessages(); // since we're in non-threaded mode, call process so that the packets are sent if (!_voxelsScriptingInterface.getVoxelPacketSender()->isThreaded()) { _voxelsScriptingInterface.getVoxelPacketSender()->process(); } } if (_entityScriptingInterface.getEntityPacketSender()->serversExist()) { // release the queue of edit entity messages. _entityScriptingInterface.getEntityPacketSender()->releaseQueuedMessages(); // since we're in non-threaded mode, call process so that the packets are sent if (!_entityScriptingInterface.getEntityPacketSender()->isThreaded()) { _entityScriptingInterface.getEntityPacketSender()->process(); } } // If we were on a thread, then wait till it's done if (thread()) { thread()->quit(); } emit finished(_fileNameString); _isRunning = false; emit runningStateChanged();} void ScriptEngine::stop() { _isFinished = true; emit runningStateChanged();} void ScriptEngine::timerFired() { QTimer* callingTimer = reinterpret_cast<QTimer*>(sender()); QScriptValue timerFunction = _timerFunctionMap.value(callingTimer); if (!callingTimer->isActive()) { // this timer is done, we can kill it _timerFunctionMap.remove(callingTimer); delete callingTimer; } // call the associated JS function, if it exists if (timerFunction.isValid()) { timerFunction.call(); }} QObject* ScriptEngine::setupTimerWithInterval(const QScriptValue& function, int intervalMS, bool isSingleShot) { // create the timer, add it to the map, and start it QTimer* newTimer = new QTimer(this); newTimer->setSingleShot(isSingleShot); connect(newTimer, &QTimer::timeout, this, &ScriptEngine::timerFired); // make sure the timer stops when the script does connect(this, &ScriptEngine::scriptEnding, newTimer, &QTimer::stop); _timerFunctionMap.insert(newTimer, function); newTimer->start(intervalMS); return newTimer;} QObject* ScriptEngine::setInterval(const QScriptValue& function, int intervalMS) { return setupTimerWithInterval(function, intervalMS, false);} QObject* ScriptEngine::setTimeout(const QScriptValue& function, int timeoutMS) { return setupTimerWithInterval(function, timeoutMS, true);} void ScriptEngine::stopTimer(QTimer *timer) { if (_timerFunctionMap.contains(timer)) { timer->stop(); _timerFunctionMap.remove(timer); delete timer; }} QUrl ScriptEngine::resolvePath(const QString& include) const { // first lets check to see if it's already a full URL QUrl url(include); if (!url.scheme().isEmpty()) { return url; } // we apparently weren't a fully qualified url, so, let's assume we're relative // to the original URL of our script QUrl parentURL(_fileNameString); // if the parent URL's scheme is empty, then this is probably a local file... if (parentURL.scheme().isEmpty()) { parentURL = QUrl::fromLocalFile(_fileNameString); } // at this point we should have a legitimate fully qualified URL for our parent url = parentURL.resolved(url); return url;} void ScriptEngine::print(const QString& message) { emit printedMessage(message);} void ScriptEngine::include(const QString& includeFile) { QUrl url = resolvePath(includeFile); QString includeContents; if (url.scheme() == "http" || url.scheme() == "https" || url.scheme() == "ftp") { QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); QNetworkReply* reply = networkAccessManager.get(QNetworkRequest(url)); qDebug() << "Downloading included script at" << includeFile; QEventLoop loop; QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); loop.exec(); includeContents = reply->readAll(); } else {#ifdef _WIN32 QString fileName = url.toString();#else QString fileName = url.toLocalFile();#endif QFile scriptFile(fileName); if (scriptFile.open(QFile::ReadOnly | QFile::Text)) { qDebug() << "Including file:" << fileName; QTextStream in(&scriptFile); includeContents = in.readAll(); } else { qDebug() << "ERROR Including file:" << fileName; emit errorMessage("ERROR Including file:" + fileName); } } QScriptValue result = evaluate(includeContents); if (hasUncaughtException()) { int line = uncaughtExceptionLineNumber(); qDebug() << "Uncaught exception at (" << includeFile << ") line" << line << ":" << result.toString(); emit errorMessage("Uncaught exception at (" + includeFile + ") line" + QString::number(line) + ":" + result.toString()); clearExceptions(); }} void ScriptEngine::load(const QString& loadFile) { QUrl url = resolvePath(loadFile); emit loadScript(url.toString(), false);} void ScriptEngine::nodeKilled(SharedNodePointer node) { _outgoingScriptAudioSequenceNumbers.remove(node->getUUID());}Lines 501–674 of 674. Previous lines
qint64 now = usecTimestampNow(); float deltaTime = (float) (now - lastUpdate) / (float) USECS_PER_SECOND; if (hasUncaughtException()) { int line = uncaughtExceptionLineNumber(); qDebug() << "Uncaught exception at (" << _fileNameString << ") line" << line << ":" << uncaughtException().toString(); emit errorMessage("Uncaught exception at (" + _fileNameString + ") line" + QString::number(line) + ":" + uncaughtException().toString()); clearExceptions(); } emit update(deltaTime); lastUpdate = now; } emit scriptEnding(); // kill the avatar identity timer delete _avatarIdentityTimer; if (_voxelsScriptingInterface.getVoxelPacketSender()->serversExist()) { // release the queue of edit voxel messages. _voxelsScriptingInterface.getVoxelPacketSender()->releaseQueuedMessages(); // since we're in non-threaded mode, call process so that the packets are sent if (!_voxelsScriptingInterface.getVoxelPacketSender()->isThreaded()) { _voxelsScriptingInterface.getVoxelPacketSender()->process(); } } if (_entityScriptingInterface.getEntityPacketSender()->serversExist()) { // release the queue of edit entity messages. _entityScriptingInterface.getEntityPacketSender()->releaseQueuedMessages(); // since we're in non-threaded mode, call process so that the packets are sent if (!_entityScriptingInterface.getEntityPacketSender()->isThreaded()) { _entityScriptingInterface.getEntityPacketSender()->process(); } } // If we were on a thread, then wait till it's done if (thread()) { thread()->quit(); } emit finished(_fileNameString); _isRunning = false; emit runningStateChanged(); } void ScriptEngine::stop() { _isFinished = true; emit runningStateChanged(); } void ScriptEngine::timerFired() { QTimer* callingTimer = reinterpret_cast<QTimer*>(sender()); QScriptValue timerFunction = _timerFunctionMap.value(callingTimer); if (!callingTimer->isActive()) { // this timer is done, we can kill it _timerFunctionMap.remove(callingTimer); delete callingTimer; } // call the associated JS function, if it exists if (timerFunction.isValid()) { timerFunction.call(); } } QObject* ScriptEngine::setupTimerWithInterval(const QScriptValue& function, int intervalMS, bool isSingleShot) { // create the timer, add it to the map, and start it QTimer* newTimer = new QTimer(this); newTimer->setSingleShot(isSingleShot); connect(newTimer, &QTimer::timeout, this, &ScriptEngine::timerFired); // make sure the timer stops when the script does connect(this, &ScriptEngine::scriptEnding, newTimer, &QTimer::stop); _timerFunctionMap.insert(newTimer, function); newTimer->start(intervalMS); return newTimer; } QObject* ScriptEngine::setInterval(const QScriptValue& function, int intervalMS) { return setupTimerWithInterval(function, intervalMS, false); } QObject* ScriptEngine::setTimeout(const QScriptValue& function, int timeoutMS) { return setupTimerWithInterval(function, timeoutMS, true); } void ScriptEngine::stopTimer(QTimer *timer) { if (_timerFunctionMap.contains(timer)) { timer->stop(); _timerFunctionMap.remove(timer); delete timer; } } QUrl ScriptEngine::resolvePath(const QString& include) const { // first lets check to see if it's already a full URL QUrl url(include); if (!url.scheme().isEmpty()) { return url; } // we apparently weren't a fully qualified url, so, let's assume we're relative // to the original URL of our script QUrl parentURL(_fileNameString); // if the parent URL's scheme is empty, then this is probably a local file... if (parentURL.scheme().isEmpty()) { parentURL = QUrl::fromLocalFile(_fileNameString); } // at this point we should have a legitimate fully qualified URL for our parent url = parentURL.resolved(url); return url; } void ScriptEngine::print(const QString& message) { emit printedMessage(message); } void ScriptEngine::include(const QString& includeFile) { QUrl url = resolvePath(includeFile); QString includeContents; if (url.scheme() == "http" || url.scheme() == "https" || url.scheme() == "ftp") { QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); QNetworkReply* reply = networkAccessManager.get(QNetworkRequest(url)); qDebug() << "Downloading included script at" << includeFile; QEventLoop loop; QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); loop.exec(); includeContents = reply->readAll(); } else { #ifdef _WIN32 QString fileName = url.toString(); #else QString fileName = url.toLocalFile(); #endif QFile scriptFile(fileName); if (scriptFile.open(QFile::ReadOnly | QFile::Text)) { qDebug() << "Including file:" << fileName; QTextStream in(&scriptFile); includeContents = in.readAll(); } else { qDebug() << "ERROR Including file:" << fileName; emit errorMessage("ERROR Including file:" + fileName); } } QScriptValue result = evaluate(includeContents); if (hasUncaughtException()) { int line = uncaughtExceptionLineNumber(); qDebug() << "Uncaught exception at (" << includeFile << ") line" << line << ":" << result.toString(); emit errorMessage("Uncaught exception at (" + includeFile + ") line" + QString::number(line) + ":" + result.toString()); clearExceptions(); } } void ScriptEngine::load(const QString& loadFile) { QUrl url = resolvePath(loadFile); emit loadScript(url.toString(), false); } void ScriptEngine::nodeKilled(SharedNodePointer node) { _outgoingScriptAudioSequenceNumbers.remove(node->getUUID()); }