Showing the changes to libraries/script-engine/src/ScriptEngine.cpp (1 of 8 files). Show all
Unified · Split
| @@ -258,6 +258,15 @@ void ScriptEngine::errorInLoadingScript(const QUrl& url) { · 257 unmodified lines | |||
| 258 | } | 258 | } |
| 259 | } | 259 | } |
| 260 | 260 | ||
| 261 | // Even though we never pass AnimVariantMap directly to and from javascript, the queued invokeMethod of | ||
| 262 | // invokeAnimationCallback requires that the type be registered. | ||
| 263 | static QScriptValue animVarMapToScriptValue(QScriptEngine* engine, const AnimVariantMap& parameters) { | ||
| 264 | return parameters.animVariantMapToScriptValue(engine); | ||
| 265 | } | ||
| 266 | static void animVarMapFromScriptValue(const QScriptValue& value, AnimVariantMap& parameters) { | ||
| 267 | parameters.animVariantMapFromScriptValue(value); | ||
| 268 | } | ||
| 269 | |||
| 261 | void ScriptEngine::init() { | 270 | void ScriptEngine::init() { |
| 262 | if (_isInitialized) { | 271 | if (_isInitialized) { |
| 263 | return; // only initialize once | 272 | return; // only initialize once |
| @@ -316,6 +325,7 @@ void ScriptEngine::init() { · 52 unmodified lines | |||
| 316 | registerGlobalObject("Vec3", &_vec3Library); | 325 | registerGlobalObject("Vec3", &_vec3Library); |
| 317 | registerGlobalObject("Uuid", &_uuidLibrary); | 326 | registerGlobalObject("Uuid", &_uuidLibrary); |
| 318 | registerGlobalObject("AnimationCache", DependencyManager::get<AnimationCache>().data()); | 327 | registerGlobalObject("AnimationCache", DependencyManager::get<AnimationCache>().data()); |
| 328 | qScriptRegisterMetaType(this, animVarMapToScriptValue, animVarMapFromScriptValue); | ||
| 319 | 329 | ||
| 320 | // constants | 330 | // constants |
| 321 | globalObject().setProperty("TREE_SCALE", newVariant(QVariant(TREE_SCALE))); | 331 | globalObject().setProperty("TREE_SCALE", newVariant(QVariant(TREE_SCALE))); |
| @@ -718,6 +728,21 @@ void ScriptEngine::stop() { · 396 unmodified lines | |||
| 718 | } | 728 | } |
| 719 | } | 729 | } |
| 720 | 730 | ||
| 731 | // Other threads can invoke this through invokeMethod, which causes the callback to be asynchronously executed in this script's thread. | ||
| 732 | void ScriptEngine::invokeAnimationCallback(QScriptValue callback, AnimVariantMap parameters) { | ||
| 733 | checkThread(); | ||
| 734 | QScriptValue javascriptParametgers = parameters.animVariantMapToScriptValue(this); | ||
| 735 | QScriptValueList callingArguments; | ||
| 736 | callingArguments << javascriptParametgers; | ||
| 737 | QScriptValue result = callback.call(QScriptValue(), callingArguments); | ||
| 738 | // We want to give the result back to the rig, but we don't have the rig or the avatar. But the global does. | ||
| 739 | // This is sort of like going through DependencyManager.get. | ||
| 740 | QScriptValue resultHandler = globalObject().property("MyAvatar").property("animationStateHandlerResult"); | ||
| 741 | QScriptValueList resultArguments; | ||
| 742 | resultArguments << callback << result; | ||
| 743 | resultHandler.call(QScriptValue(), resultArguments); // Call it synchronously, on our own time and thread. | ||
| 744 | } | ||
| 745 | |||
| 721 | void ScriptEngine::timerFired() { | 746 | void ScriptEngine::timerFired() { |
| 722 | QTimer* callingTimer = reinterpret_cast<QTimer*>(sender()); | 747 | QTimer* callingTimer = reinterpret_cast<QTimer*>(sender()); |
| 723 | QScriptValue timerFunction = _timerFunctionMap.value(callingTimer); | 748 | QScriptValue timerFunction = _timerFunctionMap.value(callingTimer); |
| @@ -898,14 +923,20 @@ void ScriptEngine::load(const QString& loadFile) { · 174 unmodified lines | |||
| 898 | } | 923 | } |
| 899 | } | 924 | } |
| 900 | 925 | ||
| 901 | // Look up the handler associated with eventName and entityID. If found, evalute the argGenerator thunk and call the handler with those args | 926 | bool ScriptEngine::checkThread() const { |
| 902 | void ScriptEngine::generalHandler(const EntityItemID& entityID, const QString& eventName, std::function<QScriptValueList()> argGenerator) { | ||
| 903 | if (QThread::currentThread() != thread()) { | 927 | if (QThread::currentThread() != thread()) { |
| 904 | qDebug() << "*** ERROR *** ScriptEngine::generalHandler() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "]"; | 928 | qDebug() << "*** ERROR *** ScriptEngine::generalHandler() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "]"; |
| 905 | assert(false); | 929 | assert(false); |
| 906 | return; | 930 | return true; |
| 907 | } | 931 | } |
| 932 | return false; | ||
| 933 | } | ||
| 908 | 934 | ||
| 935 | // Look up the handler associated with eventName and entityID. If found, evalute the argGenerator thunk and call the handler with those args | ||
| 936 | void ScriptEngine::generalHandler(const EntityItemID& entityID, const QString& eventName, std::function<QScriptValueList()> argGenerator) { | ||
| 937 | if (checkThread()) { | ||
| 938 | return; | ||
| 939 | } | ||
| 909 | if (!_registeredHandlers.contains(entityID)) { | 940 | if (!_registeredHandlers.contains(entityID)) { |
| 910 | return; | 941 | return; |
| 911 | } | 942 | } |