overte/libraries/scriptengine/src/ScriptEngine.cpp
2013-12-16 12:13:36 -08:00

169 lines
5.4 KiB
C++

//
// Agent.cpp
// hifi
//
// Created by Brad Hefta-Gaub on 12/14/13.
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
//
#include <QtCore/QCoreApplication>
#include <QtCore/QEventLoop>
#include <QtCore/QTimer>
#include <QtCore/QThread>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkReply>
#include <AvatarData.h>
#include <NodeList.h>
#include <PacketHeaders.h>
#include <UUID.h>
#include <VoxelConstants.h>
#include "ScriptEngine.h"
int ScriptEngine::_scriptNumber = 1;
ScriptEngine::ScriptEngine(QString scriptContents, bool wantMenuItems,
const char* scriptMenuName, AbstractMenuInterface* menu) {
_scriptContents = scriptContents;
_isFinished = false;
_wantMenuItems = wantMenuItems;
if (scriptMenuName) {
_scriptMenuName = "Stop ";
_scriptMenuName.append(scriptMenuName);
} else {
_scriptMenuName = "Stop Script ";
_scriptNumber++;
_scriptMenuName.append(_scriptNumber);
}
_menu = menu;
}
ScriptEngine::~ScriptEngine() {
//printf("ScriptEngine::~ScriptEngine()...\n");
}
void ScriptEngine::setupMenuItems() {
if (_menu && _wantMenuItems) {
_menu->addActionToQMenuAndActionHash(_menu->getActiveScriptsMenu(), _scriptMenuName, 0, this, SLOT(stop()));
}
}
void ScriptEngine::cleanMenuItems() {
if (_menu && _wantMenuItems) {
_menu->removeAction(_menu->getActiveScriptsMenu(), _scriptMenuName);
}
}
void ScriptEngine::run() {
//setupMenuItems();
QScriptEngine engine;
_voxelScriptingInterface.init();
_particleScriptingInterface.init();
// register meta-type for glm::vec3 conversions
registerMetaTypes(&engine);
QScriptValue agentValue = engine.newQObject(this);
engine.globalObject().setProperty("Agent", agentValue);
QScriptValue voxelScripterValue = engine.newQObject(&_voxelScriptingInterface);
engine.globalObject().setProperty("Voxels", voxelScripterValue);
QScriptValue particleScripterValue = engine.newQObject(&_particleScriptingInterface);
engine.globalObject().setProperty("Particles", particleScripterValue);
QScriptValue treeScaleValue = engine.newVariant(QVariant(TREE_SCALE));
engine.globalObject().setProperty("TREE_SCALE", treeScaleValue);
const unsigned int VISUAL_DATA_CALLBACK_USECS = (1.0 / 60.0) * 1000 * 1000;
// let the VoxelPacketSender know how frequently we plan to call it
_voxelScriptingInterface.getVoxelPacketSender()->setProcessCallIntervalHint(VISUAL_DATA_CALLBACK_USECS);
_particleScriptingInterface.getParticlePacketSender()->setProcessCallIntervalHint(VISUAL_DATA_CALLBACK_USECS);
//qDebug() << "Script:\n" << _scriptContents << "\n";
QScriptValue result = engine.evaluate(_scriptContents);
qDebug() << "Evaluated script.\n";
if (engine.hasUncaughtException()) {
int line = engine.uncaughtExceptionLineNumber();
qDebug() << "Uncaught exception at line" << line << ":" << result.toString() << "\n";
}
timeval startTime;
gettimeofday(&startTime, NULL);
int thisFrame = 0;
while (!_isFinished) {
int usecToSleep = usecTimestamp(&startTime) + (thisFrame++ * VISUAL_DATA_CALLBACK_USECS) - usecTimestampNow();
if (usecToSleep > 0) {
usleep(usecToSleep);
}
if (_isFinished) {
//qDebug() << "line: " << __LINE__ << " _isFinished... breaking loop\n";
break;
}
QCoreApplication::processEvents();
if (_isFinished) {
//qDebug() << "line: " << __LINE__ << " _isFinished... breaking loop\n";
break;
}
bool willSendVisualDataCallBack = false;
if (_voxelScriptingInterface.getVoxelPacketSender()->serversExist()) {
// allow the scripter's call back to setup visual data
willSendVisualDataCallBack = true;
// release the queue of edit voxel messages.
_voxelScriptingInterface.getVoxelPacketSender()->releaseQueuedMessages();
// since we're in non-threaded mode, call process so that the packets are sent
//_voxelScriptingInterface.getVoxelPacketSender()->process();
}
if (_particleScriptingInterface.getParticlePacketSender()->serversExist()) {
// allow the scripter's call back to setup visual data
willSendVisualDataCallBack = true;
// release the queue of edit voxel messages.
_particleScriptingInterface.getParticlePacketSender()->releaseQueuedMessages();
// since we're in non-threaded mode, call process so that the packets are sent
//_particleScriptingInterface.getParticlePacketSender()->process();
}
if (willSendVisualDataCallBack) {
emit willSendVisualDataCallback();
}
if (engine.hasUncaughtException()) {
int line = engine.uncaughtExceptionLineNumber();
qDebug() << "Uncaught exception at line" << line << ":" << engine.uncaughtException().toString() << "\n";
}
}
cleanMenuItems();
// If we were on a thread, then wait till it's done
if (thread()) {
thread()->quit();
}
emit finished();
}
void ScriptEngine::stop() {
_isFinished = true;
}