1266 lines · 52.5 KB · C++
RawDownload
            Q_ARG(const EntityItemID&, entityID),            Q_ARG(const QString&, entityScript),            Q_ARG(bool, forceRedownload));        return;    }    #ifdef THREAD_DEBUGGING    qDebug() << "ScriptEngine::loadEntityScript() called on correct thread [" << thread() << "]  "        "entityID:" << entityID << "entityScript:" << entityScript << "forceRedownload:" << forceRedownload;    #endif     // If we've been called our known entityScripts should not know about us..    assert(!_entityScripts.contains(entityID));     #ifdef THREAD_DEBUGGING    qDebug() << "ScriptEngine::loadEntityScript() calling scriptCache->getScriptContents() on thread [" << QThread::currentThread() << "] expected thread [" << thread() << "]";    #endif    DependencyManager::get<ScriptCache>()->getScriptContents(entityScript, [=](const QString& scriptOrURL, const QString& contents, bool isURL, bool success) {            #ifdef THREAD_DEBUGGING            qDebug() << "ScriptEngine::entityScriptContentAvailable() IN LAMBDA contentAvailable on thread [" << QThread::currentThread() << "] expected thread [" << thread() << "]";            #endif             this->entityScriptContentAvailable(entityID, scriptOrURL, contents, isURL, success);        }, forceRedownload);} // since all of these operations can be asynch we will always do the actual work in the response handler// for the downloadvoid ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, const QString& scriptOrURL, const QString& contents, bool isURL, bool success) {    if (QThread::currentThread() != thread()) {        #ifdef THREAD_DEBUGGING        qDebug() << "*** WARNING *** ScriptEngine::entityScriptContentAvailable() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "]  "            "entityID:" << entityID << "scriptOrURL:" << scriptOrURL << "contents:" << contents << "isURL:" << isURL << "success:" << success;        #endif         QMetaObject::invokeMethod(this, "entityScriptContentAvailable",            Q_ARG(const EntityItemID&, entityID),            Q_ARG(const QString&, scriptOrURL),            Q_ARG(const QString&, contents),            Q_ARG(bool, isURL),            Q_ARG(bool, success));        return;    }     #ifdef THREAD_DEBUGGING    qDebug() << "ScriptEngine::entityScriptContentAvailable() thread [" << QThread::currentThread() << "] expected thread [" << thread() << "]";    #endif     auto scriptCache = DependencyManager::get<ScriptCache>();    bool isFileUrl = isURL && scriptOrURL.startsWith("file://");    auto fileName = QString("(EntityID:%1, %2)").arg(entityID.toString(), isURL ? scriptOrURL : "EmbededEntityScript");     QScriptProgram program(contents, fileName);    if (!hasCorrectSyntax(program)) {        if (!isFileUrl) {            scriptCache->addScriptToBadScriptList(scriptOrURL);        }        return; // done processing script    }     if (isURL) {        setParentURL(scriptOrURL);    }     QScriptEngine sandbox;    QScriptValue testConstructor = sandbox.evaluate(program);    if (hadUncaughtExceptions(sandbox, program.fileName())) {        return;    }        if (!testConstructor.isFunction()) {        qCDebug(scriptengine) << "ScriptEngine::loadEntityScript() entity:" << entityID << "\n"                                 "    NOT CONSTRUCTOR\n"                                 "    SCRIPT:" << scriptOrURL;        if (!isFileUrl) {            scriptCache->addScriptToBadScriptList(scriptOrURL);        }        return; // done processing script    }     int64_t lastModified = 0;    if (isFileUrl) {        QString file = QUrl(scriptOrURL).toLocalFile();        lastModified = (quint64)QFileInfo(file).lastModified().toMSecsSinceEpoch();    }     QScriptValue entityScriptConstructor = evaluate(contents, fileName);    QScriptValue entityScriptObject = entityScriptConstructor.construct();    EntityScriptDetails newDetails = { scriptOrURL, entityScriptObject, lastModified };    _entityScripts[entityID] = newDetails;    if (isURL) {        setParentURL("");    }     // if we got this far, then call the preload method    callEntityScriptMethod(entityID, "preload");} void ScriptEngine::unloadEntityScript(const EntityItemID& entityID) {    if (QThread::currentThread() != thread()) {        #ifdef THREAD_DEBUGGING        qDebug() << "*** WARNING *** ScriptEngine::unloadEntityScript() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "]  "            "entityID:" << entityID;        #endif         QMetaObject::invokeMethod(this, "unloadEntityScript",            Q_ARG(const EntityItemID&, entityID));        return;    }    #ifdef THREAD_DEBUGGING    qDebug() << "ScriptEngine::unloadEntityScript() called on correct thread [" << thread() << "]  "        "entityID:" << entityID;    #endif     if (_entityScripts.contains(entityID)) {        callEntityScriptMethod(entityID, "unload");        _entityScripts.remove(entityID);    }} void ScriptEngine::unloadAllEntityScripts() {    if (QThread::currentThread() != thread()) {#ifdef THREAD_DEBUGGING        qDebug() << "*** WARNING *** ScriptEngine::unloadAllEntityScripts() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "]";#endif         QMetaObject::invokeMethod(this, "unloadAllEntityScripts");        return;    }#ifdef THREAD_DEBUGGING    qDebug() << "ScriptEngine::unloadAllEntityScripts() called on correct thread [" << thread() << "]";#endif    foreach(const EntityItemID& entityID, _entityScripts.keys()) {        callEntityScriptMethod(entityID, "unload");    }    _entityScripts.clear();} void ScriptEngine::refreshFileScript(const EntityItemID& entityID) {    if (!_entityScripts.contains(entityID)) {        return;    }     static bool recurseGuard = false;    if (recurseGuard) {        return;    }    recurseGuard = true;     EntityScriptDetails details = _entityScripts[entityID];    // Check to see if a file based script needs to be reloaded (easier debugging)    if (details.lastModified > 0) {        QString filePath = QUrl(details.scriptText).toLocalFile();        auto lastModified = QFileInfo(filePath).lastModified().toMSecsSinceEpoch();        if (lastModified > details.lastModified) {            qDebug() << "Reloading modified script " << details.scriptText;             QFile file(filePath);            file.open(QIODevice::ReadOnly);            QString scriptContents = QTextStream(&file).readAll();            this->unloadEntityScript(entityID);            this->entityScriptContentAvailable(entityID, details.scriptText, scriptContents, true, true);            if (!_entityScripts.contains(entityID)) {                qWarning() << "Reload script " << details.scriptText << " failed";            } else {                details = _entityScripts[entityID];            }        }    }    recurseGuard = false;}  void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName) {    if (QThread::currentThread() != thread()) {        #ifdef THREAD_DEBUGGING        qDebug() << "*** WARNING *** ScriptEngine::callEntityScriptMethod() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "]  "            "entityID:" << entityID << "methodName:" << methodName;        #endif         QMetaObject::invokeMethod(this, "callEntityScriptMethod",            Q_ARG(const EntityItemID&, entityID),            Q_ARG(const QString&, methodName));        return;    }    #ifdef THREAD_DEBUGGING    qDebug() << "ScriptEngine::callEntityScriptMethod() called on correct thread [" << thread() << "]  "        "entityID:" << entityID << "methodName:" << methodName;    #endif     refreshFileScript(entityID);    if (_entityScripts.contains(entityID)) {        EntityScriptDetails details = _entityScripts[entityID];        QScriptValue entityScript = details.scriptObject; // previously loaded        if (entityScript.property(methodName).isFunction()) {            QScriptValueList args;            args << entityID.toScriptValue(this);            entityScript.property(methodName).call(entityScript, args);        }     }} void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const MouseEvent& event) {    if (QThread::currentThread() != thread()) {        #ifdef THREAD_DEBUGGING        qDebug() << "*** WARNING *** ScriptEngine::callEntityScriptMethod() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "]  "            "entityID:" << entityID << "methodName:" << methodName << "event: mouseEvent";        #endif         QMetaObject::invokeMethod(this, "callEntityScriptMethod",            Q_ARG(const EntityItemID&, entityID),            Q_ARG(const QString&, methodName),            Q_ARG(const MouseEvent&, event));        return;    }    #ifdef THREAD_DEBUGGING    qDebug() << "ScriptEngine::callEntityScriptMethod() called on correct thread [" << thread() << "]  "        "entityID:" << entityID << "methodName:" << methodName << "event: mouseEvent";    #endif     refreshFileScript(entityID);    if (_entityScripts.contains(entityID)) {        EntityScriptDetails details = _entityScripts[entityID];        QScriptValue entityScript = details.scriptObject; // previously loaded        if (entityScript.property(methodName).isFunction()) {            QScriptValueList args;            args << entityID.toScriptValue(this);            args << event.toScriptValue(this);            entityScript.property(methodName).call(entityScript, args);        }    }}  void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const EntityItemID& otherID, const Collision& collision) {    if (QThread::currentThread() != thread()) {        #ifdef THREAD_DEBUGGING        qDebug() << "*** WARNING *** ScriptEngine::callEntityScriptMethod() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "]  "            "entityID:" << entityID << "methodName:" << methodName << "otherID:" << otherID << "collision: collision";        #endif         QMetaObject::invokeMethod(this, "callEntityScriptMethod",            Q_ARG(const EntityItemID&, entityID),            Q_ARG(const QString&, methodName),            Q_ARG(const EntityItemID&, otherID),            Q_ARG(const Collision&, collision));        return;    }    #ifdef THREAD_DEBUGGING    qDebug() << "ScriptEngine::callEntityScriptMethod() called on correct thread [" << thread() << "]  "        "entityID:" << entityID << "methodName:" << methodName << "otherID:" << otherID << "collision: collision";    #endif     refreshFileScript(entityID);    if (_entityScripts.contains(entityID)) {        EntityScriptDetails details = _entityScripts[entityID];        QScriptValue entityScript = details.scriptObject; // previously loaded        if (entityScript.property(methodName).isFunction()) {            QScriptValueList args;            args << entityID.toScriptValue(this);            args << otherID.toScriptValue(this);            args << collisionToScriptValue(this, collision);            entityScript.property(methodName).call(entityScript, args);        }    }}

Lines 1001–1266 of 1266. Previous lines