mirror of
https://github.com/overte-org/overte.git
synced 2025-04-22 03:04:33 +02:00
Merge pull request #1394 from ZappoMan/agent_script_engine_refactor
make Agent class use common ScriptEngine class
This commit is contained in:
commit
82f035c018
11 changed files with 58 additions and 108 deletions
|
@ -30,6 +30,7 @@ link_hifi_library(particles ${TARGET_NAME} ${ROOT_DIR})
|
|||
link_hifi_library(octree-server ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(particle-server ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(voxel-server ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(script-engine ${TARGET_NAME} ${ROOT_DIR})
|
||||
#testing
|
||||
|
||||
include_directories(${ROOT_DIR}/externals/civetweb/include)
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
Agent::Agent(const unsigned char* dataBuffer, int numBytes) :
|
||||
ThreadedAssignment(dataBuffer, numBytes)
|
||||
{
|
||||
_particleScriptingInterface.init();
|
||||
_voxelScriptingInterface.init();
|
||||
}
|
||||
|
||||
void Agent::processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr) {
|
||||
|
@ -34,12 +32,12 @@ void Agent::processDatagram(const QByteArray& dataByteArray, const HifiSockAddr&
|
|||
// PACKET_TYPE_JURISDICTION, first byte is the node type...
|
||||
switch (dataByteArray[headerBytes]) {
|
||||
case NODE_TYPE_VOXEL_SERVER:
|
||||
_voxelScriptingInterface.getJurisdictionListener()->queueReceivedPacket(senderSockAddr,
|
||||
_scriptEngine.getVoxelScriptingInterface()->getJurisdictionListener()->queueReceivedPacket(senderSockAddr,
|
||||
(unsigned char*) dataByteArray.data(),
|
||||
dataByteArray.size());
|
||||
break;
|
||||
case NODE_TYPE_PARTICLE_SERVER:
|
||||
_particleScriptingInterface.getJurisdictionListener()->queueReceivedPacket(senderSockAddr,
|
||||
_scriptEngine.getParticleScriptingInterface()->getJurisdictionListener()->queueReceivedPacket(senderSockAddr,
|
||||
(unsigned char*) dataByteArray.data(),
|
||||
dataByteArray.size());
|
||||
break;
|
||||
|
@ -76,43 +74,12 @@ void Agent::run() {
|
|||
loop.exec();
|
||||
|
||||
QString scriptContents(reply->readAll());
|
||||
QScriptEngine engine;
|
||||
|
||||
// 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() << "Downloaded script:" << 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;
|
||||
|
||||
QTimer* domainServerTimer = new QTimer(this);
|
||||
connect(domainServerTimer, SIGNAL(timeout()), this, SLOT(checkInWithDomainServerOrExit()));
|
||||
domainServerTimer->start(DOMAIN_SERVER_CHECK_IN_USECS / 1000);
|
||||
|
@ -124,50 +91,7 @@ void Agent::run() {
|
|||
QTimer* pingNodesTimer = new QTimer(this);
|
||||
connect(pingNodesTimer, SIGNAL(timeout()), nodeList, SLOT(pingInactiveNodes()));
|
||||
pingNodesTimer->start(PING_INACTIVE_NODE_INTERVAL_USECS / 1000);
|
||||
|
||||
while (!_isFinished) {
|
||||
|
||||
int usecToSleep = usecTimestamp(&startTime) + (thisFrame++ * VISUAL_DATA_CALLBACK_USECS) - usecTimestampNow();
|
||||
if (usecToSleep > 0) {
|
||||
usleep(usecToSleep);
|
||||
}
|
||||
|
||||
QCoreApplication::processEvents();
|
||||
|
||||
bool willSendVisualDataCallBack = false;
|
||||
|
||||
if (_voxelScriptingInterface.getVoxelPacketSender()->voxelServersExist()) {
|
||||
// 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";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
_scriptEngine.setScriptContents(scriptContents);
|
||||
_scriptEngine.run();
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <QtCore/QObject>
|
||||
#include <QtCore/QUrl>
|
||||
|
||||
#include <ScriptEngine.h>
|
||||
#include <ThreadedAssignment.h>
|
||||
|
||||
#include <VoxelScriptingInterface.h>
|
||||
|
@ -33,8 +34,7 @@ signals:
|
|||
void willSendAudioDataCallback();
|
||||
void willSendVisualDataCallback();
|
||||
private:
|
||||
VoxelScriptingInterface _voxelScriptingInterface;
|
||||
ParticleScriptingInterface _particleScriptingInterface;
|
||||
ScriptEngine _scriptEngine;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__Agent__) */
|
||||
|
|
|
@ -96,7 +96,7 @@ link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR})
|
|||
link_hifi_library(particles ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(avatars ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(audio ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(scriptengine ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(script-engine ${TARGET_NAME} ${ROOT_DIR})
|
||||
|
||||
# find required libraries
|
||||
find_package(Faceshift)
|
||||
|
|
|
@ -689,10 +689,10 @@ void Menu::addDisabledActionAndSeparator(QMenu* destinationMenu, const QString&
|
|||
|
||||
QAction* Menu::addActionToQMenuAndActionHash(QMenu* destinationMenu,
|
||||
const QString actionName,
|
||||
const QKeySequence& shortcut,
|
||||
const QKEYSEQUENCE& shortcut,
|
||||
const QObject* receiver,
|
||||
const char* member,
|
||||
QAction::MenuRole role) {
|
||||
QACTION_MENUROLE role) {
|
||||
QAction* action;
|
||||
|
||||
if (receiver && member) {
|
||||
|
@ -701,7 +701,7 @@ QAction* Menu::addActionToQMenuAndActionHash(QMenu* destinationMenu,
|
|||
action = destinationMenu->addAction(actionName);
|
||||
action->setShortcut(shortcut);
|
||||
}
|
||||
action->setMenuRole(role);
|
||||
action->setMenuRole((QAction::MenuRole)role);
|
||||
|
||||
_actionHash.insert(actionName, action);
|
||||
|
||||
|
@ -714,7 +714,7 @@ QAction* Menu::addCheckableActionToQMenuAndActionHash(QMenu* destinationMenu,
|
|||
const bool checked,
|
||||
const QObject* receiver,
|
||||
const char* member) {
|
||||
QAction* action = addActionToQMenuAndActionHash(destinationMenu, actionName, shortcut, receiver, member);
|
||||
QAction* action = addActionToQMenuAndActionHash(destinationMenu, actionName, (QKEYSEQUENCE&)shortcut, receiver, member);
|
||||
action->setCheckable(true);
|
||||
action->setChecked(checked);
|
||||
|
||||
|
|
|
@ -76,10 +76,10 @@ public:
|
|||
virtual QMenu* getActiveScriptsMenu() { return _activeScriptsMenu;}
|
||||
virtual QAction* addActionToQMenuAndActionHash(QMenu* destinationMenu,
|
||||
const QString actionName,
|
||||
const QKeySequence& shortcut = 0,
|
||||
const QKEYSEQUENCE& shortcut = 0,
|
||||
const QObject* receiver = NULL,
|
||||
const char* member = NULL,
|
||||
QAction::MenuRole role = QAction::NoRole);
|
||||
QACTION_MENUROLE role = NO_ROLE);
|
||||
virtual void removeAction(QMenu* menu, const QString& actionName);
|
||||
|
||||
public slots:
|
||||
|
|
|
@ -6,7 +6,7 @@ set(MACRO_DIR ${ROOT_DIR}/cmake/macros)
|
|||
# setup for find modules
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/modules/")
|
||||
|
||||
set(TARGET_NAME scriptengine)
|
||||
set(TARGET_NAME script-engine)
|
||||
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
|
|
@ -24,10 +24,13 @@
|
|||
|
||||
int ScriptEngine::_scriptNumber = 1;
|
||||
|
||||
ScriptEngine::ScriptEngine(QString scriptContents, bool wantMenuItems,
|
||||
ScriptEngine::ScriptEngine(const QString& scriptContents, bool wantMenuItems,
|
||||
const char* scriptMenuName, AbstractMenuInterface* menu) {
|
||||
_scriptContents = scriptContents;
|
||||
_isFinished = false;
|
||||
_isRunning = false;
|
||||
|
||||
// some clients will use these menu features
|
||||
_wantMenuItems = wantMenuItems;
|
||||
if (scriptMenuName) {
|
||||
_scriptMenuName = "Stop ";
|
||||
|
@ -57,10 +60,16 @@ void ScriptEngine::cleanMenuItems() {
|
|||
}
|
||||
}
|
||||
|
||||
void ScriptEngine::run() {
|
||||
bool ScriptEngine::setScriptContents(const QString& scriptContents) {
|
||||
if (_isRunning) {
|
||||
return false;
|
||||
}
|
||||
_scriptContents = scriptContents;
|
||||
return true;
|
||||
}
|
||||
|
||||
//setupMenuItems();
|
||||
|
||||
void ScriptEngine::run() {
|
||||
_isRunning = true;
|
||||
QScriptEngine engine;
|
||||
|
||||
_voxelScriptingInterface.init();
|
||||
|
@ -107,16 +116,14 @@ void ScriptEngine::run() {
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -129,7 +136,9 @@ void ScriptEngine::run() {
|
|||
_voxelScriptingInterface.getVoxelPacketSender()->releaseQueuedMessages();
|
||||
|
||||
// since we're in non-threaded mode, call process so that the packets are sent
|
||||
//_voxelScriptingInterface.getVoxelPacketSender()->process();
|
||||
if (!_voxelScriptingInterface.getVoxelPacketSender()->isThreaded()) {
|
||||
_voxelScriptingInterface.getVoxelPacketSender()->process();
|
||||
}
|
||||
}
|
||||
|
||||
if (_particleScriptingInterface.getParticlePacketSender()->serversExist()) {
|
||||
|
@ -140,14 +149,15 @@ void ScriptEngine::run() {
|
|||
_particleScriptingInterface.getParticlePacketSender()->releaseQueuedMessages();
|
||||
|
||||
// since we're in non-threaded mode, call process so that the packets are sent
|
||||
//_particleScriptingInterface.getParticlePacketSender()->process();
|
||||
if (!_particleScriptingInterface.getParticlePacketSender()->isThreaded()) {
|
||||
_particleScriptingInterface.getParticlePacketSender()->process();
|
||||
}
|
||||
}
|
||||
|
||||
if (willSendVisualDataCallBack) {
|
||||
emit willSendVisualDataCallback();
|
||||
}
|
||||
|
||||
|
||||
if (engine.hasUncaughtException()) {
|
||||
int line = engine.uncaughtExceptionLineNumber();
|
||||
qDebug() << "Uncaught exception at line" << line << ":" << engine.uncaughtException().toString() << "\n";
|
||||
|
@ -161,9 +171,11 @@ void ScriptEngine::run() {
|
|||
}
|
||||
|
||||
emit finished();
|
||||
_isRunning = false;
|
||||
}
|
||||
|
||||
void ScriptEngine::stop() {
|
||||
_isFinished = true;
|
||||
}
|
||||
|
||||
|
|
@ -19,10 +19,12 @@
|
|||
#include <ParticleScriptingInterface.h>
|
||||
#include <VoxelScriptingInterface.h>
|
||||
|
||||
const QString NO_SCRIPT("");
|
||||
|
||||
class ScriptEngine : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ScriptEngine(QString scriptContents, bool wantMenuItems = false,
|
||||
ScriptEngine(const QString& scriptContents = NO_SCRIPT, bool wantMenuItems = false,
|
||||
const char* scriptMenuName = NULL, AbstractMenuInterface* menu = NULL);
|
||||
|
||||
~ScriptEngine();
|
||||
|
@ -33,6 +35,9 @@ public:
|
|||
/// Access the ParticleScriptingInterface in order to initialize it with a custom packet sender and jurisdiction listener
|
||||
ParticleScriptingInterface* getParticleScriptingInterface() { return &_particleScriptingInterface; }
|
||||
|
||||
/// sets the script contents, will return false if failed, will fail if script is already running
|
||||
bool setScriptContents(const QString& scriptContents);
|
||||
|
||||
void setupMenuItems();
|
||||
void cleanMenuItems();
|
||||
|
||||
|
@ -47,6 +52,7 @@ signals:
|
|||
protected:
|
||||
QString _scriptContents;
|
||||
bool _isFinished;
|
||||
bool _isRunning;
|
||||
|
||||
|
||||
private:
|
|
@ -10,19 +10,26 @@
|
|||
#ifndef __hifi__AbstractMenuInterface__
|
||||
#define __hifi__AbstractMenuInterface__
|
||||
|
||||
#include <QMenuBar>
|
||||
//#include <QHash>
|
||||
//#include <QKeySequence>
|
||||
class QMenu;
|
||||
class QString;
|
||||
class QObject;
|
||||
class QKeySequence;
|
||||
class QAction;
|
||||
|
||||
// these are actually class scoped enums, but we don't want to depend on the class for this abstract interface
|
||||
const int NO_ROLE = 0;
|
||||
typedef int QACTION_MENUROLE;
|
||||
typedef int QKEYSEQUENCE;
|
||||
|
||||
class AbstractMenuInterface {
|
||||
public:
|
||||
virtual QMenu* getActiveScriptsMenu() = 0;
|
||||
virtual QAction* addActionToQMenuAndActionHash(QMenu* destinationMenu,
|
||||
const QString actionName,
|
||||
const QKeySequence& shortcut = 0,
|
||||
const QKEYSEQUENCE& shortcut = 0,
|
||||
const QObject* receiver = NULL,
|
||||
const char* member = NULL,
|
||||
QAction::MenuRole role = QAction::NoRole) = 0;
|
||||
QACTION_MENUROLE role = NO_ROLE) = 0;
|
||||
virtual void removeAction(QMenu* menu, const QString& actionName) = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -33,6 +33,8 @@ public:
|
|||
/// Override this function to do whatever your class actually does, return false to exit thread early.
|
||||
virtual bool process() = 0;
|
||||
|
||||
bool isThreaded() const { return _isThreaded; }
|
||||
|
||||
protected:
|
||||
|
||||
/// Locks all the resources of the thread.
|
||||
|
@ -43,8 +45,6 @@ protected:
|
|||
|
||||
bool isStillRunning() const { return !_stopThread; }
|
||||
|
||||
bool isThreaded() const { return _isThreaded; }
|
||||
|
||||
private:
|
||||
pthread_mutex_t _mutex;
|
||||
|
||||
|
|
Loading…
Reference in a new issue