History

Merge branch 'master' of https://github.com/worklist/hifi into controller_scripting_interface

ZappoMan committed 12 years ago

Commit 4bfdce32 parents a6e6205 82f035c35 files · +410 −271Browse files

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

Unified · Split

libraries/script-engine/src/ScriptEngine.cpp+188−0
@@ -0,0 +1,188 @@
1+//
2+// Agent.cpp
3+// hifi
4+//
5+// Created by Brad Hefta-Gaub on 12/14/13.
6+// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
7+//
8+
9+#include <QtCore/QCoreApplication>
10+#include <QtCore/QEventLoop>
11+#include <QtCore/QTimer>
12+#include <QtCore/QThread>
13+#include <QtNetwork/QNetworkAccessManager>
14+#include <QtNetwork/QNetworkRequest>
15+#include <QtNetwork/QNetworkReply>
16+
17+#include <AvatarData.h>
18+#include <NodeList.h>
19+#include <PacketHeaders.h>
20+#include <UUID.h>
21+#include <VoxelConstants.h>
22+
23+#include "ScriptEngine.h"
24+
25+int ScriptEngine::_scriptNumber = 1;
26+
27+ScriptEngine::ScriptEngine(const QString& scriptContents, bool wantMenuItems,
28+ const char* scriptMenuName, AbstractMenuInterface* menu,
29+ ControllerScriptingInterface* controllerScriptingInterface) {
30+ _scriptContents = scriptContents;
31+ _isFinished = false;
32+ _isRunning = false;
33+
34+ // some clients will use these menu features
35+ _wantMenuItems = wantMenuItems;
36+ if (scriptMenuName) {
37+ _scriptMenuName = "Stop ";
38+ _scriptMenuName.append(scriptMenuName);
39+ } else {
40+ _scriptMenuName = "Stop Script ";
41+ _scriptNumber++;
42+ _scriptMenuName.append(_scriptNumber);
43+ }
44+ _menu = menu;
45+ _controllerScriptingInterface = controllerScriptingInterface;
46+}
47+
48+ScriptEngine::~ScriptEngine() {
49+ //printf("ScriptEngine::~ScriptEngine()...\n");
50+}
51+
52+
53+void ScriptEngine::setupMenuItems() {
54+ if (_menu && _wantMenuItems) {
55+ _menu->addActionToQMenuAndActionHash(_menu->getActiveScriptsMenu(), _scriptMenuName, 0, this, SLOT(stop()));
56+ }
57+}
58+
59+void ScriptEngine::cleanMenuItems() {
60+ if (_menu && _wantMenuItems) {
61+ _menu->removeAction(_menu->getActiveScriptsMenu(), _scriptMenuName);
62+ }
63+}
64+
65+bool ScriptEngine::setScriptContents(const QString& scriptContents) {
66+ if (_isRunning) {
67+ return false;
68+ }
69+ _scriptContents = scriptContents;
70+ return true;
71+}
72+
73+void ScriptEngine::run() {
74+ _isRunning = true;
75+ QScriptEngine engine;
76+
77+ _voxelScriptingInterface.init();
78+ _particleScriptingInterface.init();
79+
80+ // register meta-type for glm::vec3 conversions
81+ registerMetaTypes(&engine);
82+
83+ QScriptValue agentValue = engine.newQObject(this);
84+ engine.globalObject().setProperty("Agent", agentValue);
85+
86+ QScriptValue voxelScripterValue = engine.newQObject(&_voxelScriptingInterface);
87+ engine.globalObject().setProperty("Voxels", voxelScripterValue);
88+
89+ QScriptValue particleScripterValue = engine.newQObject(&_particleScriptingInterface);
90+ engine.globalObject().setProperty("Particles", particleScripterValue);
91+
92+ if (_controllerScriptingInterface) {
93+ QScriptValue controllerScripterValue = engine.newQObject(_controllerScriptingInterface);
94+ engine.globalObject().setProperty("Controller", controllerScripterValue);
95+ }
96+
97+ QScriptValue treeScaleValue = engine.newVariant(QVariant(TREE_SCALE));
98+ engine.globalObject().setProperty("TREE_SCALE", treeScaleValue);
99+
100+ const unsigned int VISUAL_DATA_CALLBACK_USECS = (1.0 / 60.0) * 1000 * 1000;
101+
102+ // let the VoxelPacketSender know how frequently we plan to call it
103+ _voxelScriptingInterface.getVoxelPacketSender()->setProcessCallIntervalHint(VISUAL_DATA_CALLBACK_USECS);
104+ _particleScriptingInterface.getParticlePacketSender()->setProcessCallIntervalHint(VISUAL_DATA_CALLBACK_USECS);
105+
106+ //qDebug() << "Script:\n" << _scriptContents << "\n";
107+
108+ QScriptValue result = engine.evaluate(_scriptContents);
109+ qDebug() << "Evaluated script.\n";
110+
111+ if (engine.hasUncaughtException()) {
112+ int line = engine.uncaughtExceptionLineNumber();
113+ qDebug() << "Uncaught exception at line" << line << ":" << result.toString() << "\n";
114+ }
115+
116+ timeval startTime;
117+ gettimeofday(&startTime, NULL);
118+
119+ int thisFrame = 0;
120+
121+ while (!_isFinished) {
122+ int usecToSleep = usecTimestamp(&startTime) + (thisFrame++ * VISUAL_DATA_CALLBACK_USECS) - usecTimestampNow();
123+ if (usecToSleep > 0) {
124+ usleep(usecToSleep);
125+ }
126+
127+ if (_isFinished) {
128+ break;
129+ }
130+
131+ QCoreApplication::processEvents();
132+
133+ if (_isFinished) {
134+ break;
135+ }
136+
137+ bool willSendVisualDataCallBack = false;
138+ if (_voxelScriptingInterface.getVoxelPacketSender()->serversExist()) {
139+ // allow the scripter's call back to setup visual data
140+ willSendVisualDataCallBack = true;
141+
142+ // release the queue of edit voxel messages.
143+ _voxelScriptingInterface.getVoxelPacketSender()->releaseQueuedMessages();
144+
145+ // since we're in non-threaded mode, call process so that the packets are sent
146+ if (!_voxelScriptingInterface.getVoxelPacketSender()->isThreaded()) {
147+ _voxelScriptingInterface.getVoxelPacketSender()->process();
148+ }
149+ }
150+
151+ if (_particleScriptingInterface.getParticlePacketSender()->serversExist()) {
152+ // allow the scripter's call back to setup visual data
153+ willSendVisualDataCallBack = true;
154+
155+ // release the queue of edit voxel messages.
156+ _particleScriptingInterface.getParticlePacketSender()->releaseQueuedMessages();
157+
158+ // since we're in non-threaded mode, call process so that the packets are sent
159+ if (!_particleScriptingInterface.getParticlePacketSender()->isThreaded()) {
160+ _particleScriptingInterface.getParticlePacketSender()->process();
161+ }
162+ }
163+
164+ if (willSendVisualDataCallBack) {
165+ emit willSendVisualDataCallback();
166+ }
167+
168+ if (engine.hasUncaughtException()) {
169+ int line = engine.uncaughtExceptionLineNumber();
170+ qDebug() << "Uncaught exception at line" << line << ":" << engine.uncaughtException().toString() << "\n";
171+ }
172+ }
173+ cleanMenuItems();
174+
175+ // If we were on a thread, then wait till it's done
176+ if (thread()) {
177+ thread()->quit();
178+ }
179+
180+ emit finished();
181+ _isRunning = false;
182+}
183+
184+void ScriptEngine::stop() {
185+ _isFinished = true;
186+}
187+
188+