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 | #include <QtNetwork/QNetworkRequest> | 16 | #include <QtNetwork/QNetworkRequest> |
| 17 | #include <QtNetwork/QNetworkReply> | 17 | #include <QtNetwork/QNetworkReply> |
| 18 | #include <QScriptEngine> | 18 | #include <QScriptEngine> |
| 19 | #include <QScriptValue> | ||
| 19 | 20 | ||
| 20 | #include <AudioConstants.h> | 21 | #include <AudioConstants.h> |
| 21 | #include <AudioEffectOptions.h> | 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 | } | ||