Showing the changes to libraries/script-engine/src/ScriptEngine.cpp (1 of 6 files). Show all
Unified · Split
| @@ -16,6 +16,7 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <QtNetwork/QNetworkRequest> |
| 17 | 17 | #include <QtNetwork/QNetworkReply> |
| 18 | 18 | #include <QScriptEngine> |
| 19 | +#include <QScriptValue> | |
| 19 | 20 | |
| 20 | 21 | #include <AudioConstants.h> |
| 21 | 22 | #include <AudioEffectOptions.h> |
| @@ -848,3 +849,181 @@ void ScriptEngine::generalHandler(const EntityItemID& entityID, const QString& e · 826 unmodified lines | ||
| 848 | 849 | } |
| 849 | 850 | } |
| 850 | 851 | } |
| 852 | + | |
| 853 | +// since all of these operations can be asynch we will always do the actual work in the response handler | |
| 854 | +// for the download | |
| 855 | +void ScriptEngine::loadEntityScript(const EntityItemID& entityID, const QString& entityScript, bool forceRedownload) { | |
| 856 | + if (QThread::currentThread() != thread()) { | |
| 857 | + qDebug() << "*** WARNING *** ScriptEngine::loadEntityScript() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] " | |
| 858 | + "entityID:" << entityID << | |
| 859 | + "entityScript:" << entityScript << | |
| 860 | + "forceRedownload:" << forceRedownload; | |
| 861 | + | |
| 862 | + QMetaObject::invokeMethod(this, "loadEntityScript", | |
| 863 | + Q_ARG(const EntityItemID&, entityID), | |
| 864 | + Q_ARG(const QString&, entityScript), | |
| 865 | + Q_ARG(bool, forceRedownload)); | |
| 866 | + return; | |
| 867 | + } | |
| 868 | + qDebug() << "ScriptEngine::loadEntityScript() called on correct thread [" << thread() << "] " | |
| 869 | + "entityID:" << entityID << | |
| 870 | + "entityScript:" << entityScript << | |
| 871 | + "forceRedownload:" << forceRedownload; | |
| 872 | + | |
| 873 | + // If we've been called our known entityScripts should not know about us.. | |
| 874 | + assert(!_entityScripts.contains(entityID)); | |
| 875 | + | |
| 876 | + auto scriptCache = DependencyManager::get<ScriptCache>(); | |
| 877 | + | |
| 878 | + scriptCache->getScriptContents(entityScript, [=](const QString& scriptOrURL, const QString& contents, bool isURL, bool success) { | |
| 879 | + | |
| 880 | + // first check the syntax of the script contents | |
| 881 | + QScriptSyntaxCheckResult syntaxCheck = QScriptEngine::checkSyntax(contents); | |
| 882 | + if (syntaxCheck.state() != QScriptSyntaxCheckResult::Valid) { | |
| 883 | + qCDebug(scriptengine) << "ScriptEngine::loadEntityScript() entity:" << entityID; | |
| 884 | + qCDebug(scriptengine) << " " << syntaxCheck.errorMessage() << ":" | |
| 885 | + << syntaxCheck.errorLineNumber() << syntaxCheck.errorColumnNumber(); | |
| 886 | + qCDebug(scriptengine) << " SCRIPT:" << scriptOrURL; | |
| 887 | + scriptCache->addScriptToBadScriptList(scriptOrURL); | |
| 888 | + return; // done processing script | |
| 889 | + } | |
| 890 | + | |
| 891 | + if (isURL) { | |
| 892 | + setParentURL(scriptOrURL); | |
| 893 | + } | |
| 894 | + | |
| 895 | + QScriptEngine sandbox; | |
| 896 | + QScriptValue testConstructor = sandbox.evaluate(contents); | |
| 897 | + | |
| 898 | + if (!testConstructor.isFunction()) { | |
| 899 | + qCDebug(scriptengine) << "ScriptEngine::loadEntityScript() entity:" << entityID; | |
| 900 | + qCDebug(scriptengine) << " NOT CONSTRUCTOR"; | |
| 901 | + qCDebug(scriptengine) << " SCRIPT:" << scriptOrURL; | |
| 902 | + scriptCache->addScriptToBadScriptList(scriptOrURL); | |
| 903 | + return; // done processing script | |
| 904 | + } | |
| 905 | + | |
| 906 | + QScriptValue entityScriptConstructor = evaluate(contents); | |
| 907 | + | |
| 908 | + QScriptValue entityScriptObject = entityScriptConstructor.construct(); | |
| 909 | + EntityScriptDetails newDetails = { scriptOrURL, entityScriptObject }; | |
| 910 | + _entityScripts[entityID] = newDetails; | |
| 911 | + | |
| 912 | + if (isURL) { | |
| 913 | + setParentURL(""); | |
| 914 | + } | |
| 915 | + | |
| 916 | + // if we got this far, then call the preload method | |
| 917 | + callEntityScriptMethod(entityID, "preload"); | |
| 918 | + | |
| 919 | + }, forceRedownload); | |
| 920 | +} | |
| 921 | + | |
| 922 | +void ScriptEngine::unloadEntityScript(const EntityItemID& entityID) { | |
| 923 | + if (QThread::currentThread() != thread()) { | |
| 924 | + qDebug() << "*** WARNING *** ScriptEngine::unloadEntityScript() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] " | |
| 925 | + "entityID:" << entityID; | |
| 926 | + | |
| 927 | + QMetaObject::invokeMethod(this, "unloadEntityScript", | |
| 928 | + Q_ARG(const EntityItemID&, entityID)); | |
| 929 | + return; | |
| 930 | + } | |
| 931 | + qDebug() << "ScriptEngine::unloadEntityScript() called on correct thread [" << thread() << "] " | |
| 932 | + "entityID:" << entityID; | |
| 933 | + | |
| 934 | + if (_entityScripts.contains(entityID)) { | |
| 935 | + callEntityScriptMethod(entityID, "unload"); | |
| 936 | + _entityScripts.remove(entityID); | |
| 937 | + } | |
| 938 | +} | |
| 939 | + | |
| 940 | +void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName) { | |
| 941 | + if (QThread::currentThread() != thread()) { | |
| 942 | + qDebug() << "*** WARNING *** ScriptEngine::callEntityScriptMethod() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] " | |
| 943 | + "entityID:" << entityID << | |
| 944 | + "methodName:" << methodName; | |
| 945 | + | |
| 946 | + QMetaObject::invokeMethod(this, "callEntityScriptMethod", | |
| 947 | + Q_ARG(const EntityItemID&, entityID), | |
| 948 | + Q_ARG(const QString&, methodName)); | |
| 949 | + return; | |
| 950 | + } | |
| 951 | + qDebug() << "ScriptEngine::callEntityScriptMethod() called on correct thread [" << thread() << "] " | |
| 952 | + "entityID:" << entityID << | |
| 953 | + "methodName:" << methodName; | |
| 954 | + | |
| 955 | + if (_entityScripts.contains(entityID)) { | |
| 956 | + EntityScriptDetails details = _entityScripts[entityID]; | |
| 957 | + QScriptValue entityScript = details.scriptObject; // previously loaded | |
| 958 | + if (entityScript.property(methodName).isFunction()) { | |
| 959 | + QScriptValueList args; | |
| 960 | + args << entityID.toScriptValue(this); | |
| 961 | + entityScript.property(methodName).call(entityScript, args); | |
| 962 | + } | |
| 963 | + } | |
| 964 | +} | |
| 965 | + | |
| 966 | +void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const MouseEvent& event) { | |
| 967 | + if (QThread::currentThread() != thread()) { | |
| 968 | + qDebug() << "*** WARNING *** ScriptEngine::callEntityScriptMethod() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] " | |
| 969 | + "entityID:" << entityID << | |
| 970 | + "methodName:" << methodName << | |
| 971 | + "event: mouseEvent"; | |
| 972 | + | |
| 973 | + QMetaObject::invokeMethod(this, "callEntityScriptMethod", | |
| 974 | + Q_ARG(const EntityItemID&, entityID), | |
| 975 | + Q_ARG(const QString&, methodName), | |
| 976 | + Q_ARG(const MouseEvent&, event)); | |
| 977 | + return; | |
| 978 | + } | |
| 979 | + qDebug() << "ScriptEngine::callEntityScriptMethod() called on correct thread [" << thread() << "] " | |
| 980 | + "entityID:" << entityID << | |
| 981 | + "methodName:" << methodName << | |
| 982 | + "event: mouseEvent"; | |
| 983 | + | |
| 984 | + if (_entityScripts.contains(entityID)) { | |
| 985 | + EntityScriptDetails details = _entityScripts[entityID]; | |
| 986 | + QScriptValue entityScript = details.scriptObject; // previously loaded | |
| 987 | + if (entityScript.property(methodName).isFunction()) { | |
| 988 | + QScriptValueList args; | |
| 989 | + args << entityID.toScriptValue(this); | |
| 990 | + args << event.toScriptValue(this); | |
| 991 | + entityScript.property(methodName).call(entityScript, args); | |
| 992 | + } | |
| 993 | + } | |
| 994 | +} | |
| 995 | + | |
| 996 | + | |
| 997 | +void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const EntityItemID& otherID, const Collision& collision) { | |
| 998 | + if (QThread::currentThread() != thread()) { | |
| 999 | + qDebug() << "*** WARNING *** ScriptEngine::callEntityScriptMethod() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] " | |
| 1000 | + "entityID:" << entityID << | |
| 1001 | + "methodName:" << methodName << | |
| 1002 | + "otherID:" << otherID << | |
| 1003 | + "collision: collision"; | |
| 1004 | + | |
| 1005 | + QMetaObject::invokeMethod(this, "callEntityScriptMethod", | |
| 1006 | + Q_ARG(const EntityItemID&, entityID), | |
| 1007 | + Q_ARG(const QString&, methodName), | |
| 1008 | + Q_ARG(const EntityItemID&, otherID), | |
| 1009 | + Q_ARG(const Collision&, collision)); | |
| 1010 | + return; | |
| 1011 | + } | |
| 1012 | + qDebug() << "ScriptEngine::callEntityScriptMethod() called on correct thread [" << thread() << "] " | |
| 1013 | + "entityID:" << entityID << | |
| 1014 | + "methodName:" << methodName << | |
| 1015 | + "otherID:" << otherID << | |
| 1016 | + "collision: collision"; | |
| 1017 | + | |
| 1018 | + if (_entityScripts.contains(entityID)) { | |
| 1019 | + EntityScriptDetails details = _entityScripts[entityID]; | |
| 1020 | + QScriptValue entityScript = details.scriptObject; // previously loaded | |
| 1021 | + if (entityScript.property(methodName).isFunction()) { | |
| 1022 | + QScriptValueList args; | |
| 1023 | + args << entityID.toScriptValue(this); | |
| 1024 | + args << otherID.toScriptValue(this); | |
| 1025 | + args << collisionToScriptValue(this, collision); | |
| 1026 | + entityScript.property(methodName).call(entityScript, args); | |
| 1027 | + } | |
| 1028 | + } | |
| 1029 | +} | |