Showing the changes to libraries/script-engine/src/ScriptEngine.cpp (1 of 305 files). Show all
Unified · Split
| @@ -28,7 +28,9 @@ · 27 unmodified lines | ||
| 28 | 28 | #include <udt/PacketHeaders.h> |
| 29 | 29 | #include <UUID.h> |
| 30 | 30 | |
| 31 | −#include "AnimationObject.h" | |
| 31 | +#include <controllers/ScriptingInterface.h> | |
| 32 | +#include <AnimationObject.h> | |
| 33 | + | |
| 32 | 34 | #include "ArrayBufferViewClass.h" |
| 33 | 35 | #include "BatchLoader.h" |
| 34 | 36 | #include "DataViewClass.h" |
| @@ -76,13 +78,16 @@ void avatarDataFromScriptValue(const QScriptValue &object, AvatarData* &out) { · 41 unmodified lines | ||
| 76 | 78 | out = qobject_cast<AvatarData*>(object.toQObject()); |
| 77 | 79 | } |
| 78 | 80 | |
| 79 | −QScriptValue inputControllerToScriptValue(QScriptEngine *engine, AbstractInputController* const &in) { | |
| 81 | +QScriptValue inputControllerToScriptValue(QScriptEngine *engine, controller::InputController* const &in) { | |
| 80 | 82 | return engine->newQObject(in); |
| 81 | 83 | } |
| 82 | −void inputControllerFromScriptValue(const QScriptValue &object, AbstractInputController* &out) { | |
| 83 | − out = qobject_cast<AbstractInputController*>(object.toQObject()); | |
| 84 | + | |
| 85 | +void inputControllerFromScriptValue(const QScriptValue &object, controller::InputController* &out) { | |
| 86 | + out = qobject_cast<controller::InputController*>(object.toQObject()); | |
| 84 | 87 | } |
| 85 | 88 | |
| 89 | + | |
| 90 | + | |
| 86 | 91 | static bool hasCorrectSyntax(const QScriptProgram& program) { |
| 87 | 92 | const auto syntaxCheck = QScriptEngine::checkSyntax(program.sourceCode()); |
| 88 | 93 | if (syntaxCheck.state() != QScriptSyntaxCheckResult::Valid) { |
| @@ -114,20 +119,17 @@ static bool hadUncaughtExceptions(QScriptEngine& engine, const QString& fileName · 25 unmodified lines | ||
| 114 | 119 | return false; |
| 115 | 120 | } |
| 116 | 121 | |
| 117 | −ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNameString, | |
| 118 | − AbstractControllerScriptingInterface* controllerScriptingInterface, bool wantSignals) : | |
| 119 | − | |
| 120 | −_scriptContents(scriptContents), | |
| 121 | −_isFinished(false), | |
| 122 | −_isRunning(false), | |
| 123 | −_isInitialized(false), | |
| 124 | −_timerFunctionMap(), | |
| 125 | −_wantSignals(wantSignals), | |
| 126 | −_controllerScriptingInterface(controllerScriptingInterface), | |
| 127 | −_fileNameString(fileNameString), | |
| 128 | −_isUserLoaded(false), | |
| 129 | −_isReloading(false), | |
| 130 | −_arrayBufferClass(new ArrayBufferClass(this)) | |
| 122 | +ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNameString, bool wantSignals) : | |
| 123 | + _scriptContents(scriptContents), | |
| 124 | + _isFinished(false), | |
| 125 | + _isRunning(false), | |
| 126 | + _isInitialized(false), | |
| 127 | + _timerFunctionMap(), | |
| 128 | + _wantSignals(wantSignals), | |
| 129 | + _fileNameString(fileNameString), | |
| 130 | + _isUserLoaded(false), | |
| 131 | + _isReloading(false), | |
| 132 | + _arrayBufferClass(new ArrayBufferClass(this)) | |
| 131 | 133 | { |
| 132 | 134 | _allScriptsMutex.lock(); |
| 133 | 135 | _allKnownScriptEngines.insert(this); |
| @@ -285,6 +287,27 @@ void ScriptEngine::errorInLoadingScript(const QUrl& url) { · 151 unmodified lines | ||
| 285 | 287 | } |
| 286 | 288 | } |
| 287 | 289 | |
| 290 | +// Even though we never pass AnimVariantMap directly to and from javascript, the queued invokeMethod of | |
| 291 | +// callAnimationStateHandler requires that the type be registered. | |
| 292 | +// These two are meaningful, if we ever do want to use them... | |
| 293 | +static QScriptValue animVarMapToScriptValue(QScriptEngine* engine, const AnimVariantMap& parameters) { | |
| 294 | + QStringList unused; | |
| 295 | + return parameters.animVariantMapToScriptValue(engine, unused, false); | |
| 296 | +} | |
| 297 | +static void animVarMapFromScriptValue(const QScriptValue& value, AnimVariantMap& parameters) { | |
| 298 | + parameters.animVariantMapFromScriptValue(value); | |
| 299 | +} | |
| 300 | +// ... while these two are not. But none of the four are ever used. | |
| 301 | +static QScriptValue resultHandlerToScriptValue(QScriptEngine* engine, const AnimVariantResultHandler& resultHandler) { | |
| 302 | + qCCritical(scriptengine) << "Attempt to marshall result handler to javascript"; | |
| 303 | + assert(false); | |
| 304 | + return QScriptValue(); | |
| 305 | +} | |
| 306 | +static void resultHandlerFromScriptValue(const QScriptValue& value, AnimVariantResultHandler& resultHandler) { | |
| 307 | + qCCritical(scriptengine) << "Attempt to marshall result handler from javascript"; | |
| 308 | + assert(false); | |
| 309 | +} | |
| 310 | + | |
| 288 | 311 | void ScriptEngine::init() { |
| 289 | 312 | if (_isInitialized) { |
| 290 | 313 | return; // only initialize once |
| @@ -337,27 +360,26 @@ void ScriptEngine::init() { · 46 unmodified lines | ||
| 337 | 360 | |
| 338 | 361 | registerGlobalObject("Script", this); |
| 339 | 362 | registerGlobalObject("Audio", &AudioScriptingInterface::getInstance()); |
| 340 | − registerGlobalObject("Controller", _controllerScriptingInterface); | |
| 341 | 363 | registerGlobalObject("Entities", entityScriptingInterface.data()); |
| 342 | 364 | registerGlobalObject("Quat", &_quatLibrary); |
| 343 | 365 | registerGlobalObject("Vec3", &_vec3Library); |
| 344 | 366 | registerGlobalObject("Uuid", &_uuidLibrary); |
| 345 | 367 | registerGlobalObject("AnimationCache", DependencyManager::get<AnimationCache>().data()); |
| 346 | − | |
| 368 | + qScriptRegisterMetaType(this, animVarMapToScriptValue, animVarMapFromScriptValue); | |
| 369 | + qScriptRegisterMetaType(this, resultHandlerToScriptValue, resultHandlerFromScriptValue); | |
| 370 | + | |
| 347 | 371 | // constants |
| 348 | 372 | globalObject().setProperty("TREE_SCALE", newVariant(QVariant(TREE_SCALE))); |
| 349 | − | |
| 350 | − if (_controllerScriptingInterface) { | |
| 351 | − _controllerScriptingInterface->registerControllerTypes(this); | |
| 352 | − } | |
| 353 | − | |
| 354 | − | |
| 373 | + | |
| 374 | + auto scriptingInterface = DependencyManager::get<controller::ScriptingInterface>(); | |
| 375 | + registerGlobalObject("Controller", scriptingInterface.data()); | |
| 376 | + UserInputMapper::registerControllerTypes(this); | |
| 355 | 377 | } |
| 356 | 378 | |
| 357 | 379 | void ScriptEngine::registerValue(const QString& valueName, QScriptValue value) { |
| 358 | 380 | if (QThread::currentThread() != thread()) { |
| 359 | 381 | #ifdef THREAD_DEBUGGING |
| 360 | − qDebug() << "*** WARNING *** ScriptEngine::registerValue() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] name:" << name; | |
| 382 | + qDebug() << "*** WARNING *** ScriptEngine::registerValue() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "]"; | |
| 361 | 383 | #endif |
| 362 | 384 | QMetaObject::invokeMethod(this, "registerValue", |
| 363 | 385 | Q_ARG(const QString&, valueName), |
| @@ -558,7 +580,7 @@ void ScriptEngine::addEventHandler(const EntityItemID& entityID, const QString& · 194 unmodified lines | ||
| 558 | 580 | auto makeCollisionHandler = [this](QString eventName) -> CollisionHandler { |
| 559 | 581 | return [this, eventName](const EntityItemID& idA, const EntityItemID& idB, const Collision& collision) { |
| 560 | 582 | forwardHandlerCall(idA, eventName, { idA.toScriptValue(this), idB.toScriptValue(this), |
| 561 | − collisionToScriptValue(this, collision) }); | |
| 583 | + collisionToScriptValue(this, collision) }); | |
| 562 | 584 | }; |
| 563 | 585 | }; |
| 564 | 586 | |
| @@ -743,6 +765,27 @@ void ScriptEngine::stop() { · 178 unmodified lines | ||
| 743 | 765 | } |
| 744 | 766 | } |
| 745 | 767 | |
| 768 | +// Other threads can invoke this through invokeMethod, which causes the callback to be asynchronously executed in this script's thread. | |
| 769 | +void ScriptEngine::callAnimationStateHandler(QScriptValue callback, AnimVariantMap parameters, QStringList names, bool useNames, AnimVariantResultHandler resultHandler) { | |
| 770 | + if (QThread::currentThread() != thread()) { | |
| 771 | +#ifdef THREAD_DEBUGGING | |
| 772 | + qDebug() << "*** WARNING *** ScriptEngine::callAnimationStateHandler() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] name:" << name; | |
| 773 | +#endif | |
| 774 | + QMetaObject::invokeMethod(this, "callAnimationStateHandler", | |
| 775 | + Q_ARG(QScriptValue, callback), | |
| 776 | + Q_ARG(AnimVariantMap, parameters), | |
| 777 | + Q_ARG(QStringList, names), | |
| 778 | + Q_ARG(bool, useNames), | |
| 779 | + Q_ARG(AnimVariantResultHandler, resultHandler)); | |
| 780 | + return; | |
| 781 | + } | |
| 782 | + QScriptValue javascriptParameters = parameters.animVariantMapToScriptValue(this, names, useNames); | |
| 783 | + QScriptValueList callingArguments; | |
| 784 | + callingArguments << javascriptParameters; | |
| 785 | + QScriptValue result = callback.call(QScriptValue(), callingArguments); | |
| 786 | + resultHandler(result); | |
| 787 | +} | |
| 788 | + | |
| 746 | 789 | void ScriptEngine::timerFired() { |
| 747 | 790 | QTimer* callingTimer = reinterpret_cast<QTimer*>(sender()); |
| 748 | 791 | QScriptValue timerFunction = _timerFunctionMap.value(callingTimer); |
| @@ -928,9 +971,8 @@ void ScriptEngine::forwardHandlerCall(const EntityItemID& entityID, const QStrin · 179 unmodified lines | ||
| 928 | 971 | if (QThread::currentThread() != thread()) { |
| 929 | 972 | qDebug() << "*** ERROR *** ScriptEngine::forwardHandlerCall() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "]"; |
| 930 | 973 | assert(false); |
| 931 | − return; | |
| 974 | + return ; | |
| 932 | 975 | } |
| 933 | − | |
| 934 | 976 | if (!_registeredHandlers.contains(entityID)) { |
| 935 | 977 | return; |
| 936 | 978 | } |