mirror of
https://github.com/lubosz/overte.git
synced 2025-04-23 16:14:01 +02:00
and the new filter class
This commit is contained in:
parent
4821180dd3
commit
c08adc9faa
2 changed files with 184 additions and 0 deletions
138
libraries/entities/src/EntityEditFilters.cpp
Normal file
138
libraries/entities/src/EntityEditFilters.cpp
Normal file
|
@ -0,0 +1,138 @@
|
|||
//
|
||||
// EntityEditFilters.cpp
|
||||
// libraries/entities/src
|
||||
//
|
||||
// Created by David Kelly on 2/7/2017.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
|
||||
#include <QUrl>
|
||||
|
||||
#include <ResourceManager.h>
|
||||
|
||||
#include "EntityEditFilters.h"
|
||||
|
||||
QScriptValue EntityEditFilters::filter(glm::vec3& position, EntityItemProperties& propertiesIn, EntityItemProperties& propertiesOut, bool& wasChanged, bool isAdd) {
|
||||
qDebug() << "in EntityEditFilters";
|
||||
return QScriptValue();
|
||||
}
|
||||
|
||||
void EntityEditFilters::removeEntityFilter(EntityItemID& entityID) {
|
||||
QScriptEngine* engine = _filterScriptEngineMap.value(entityID);
|
||||
if (engine) {
|
||||
_filterScriptEngineMap.remove(entityID);
|
||||
delete engine;
|
||||
}
|
||||
FilterFunctionPair* pair = _filterFunctionMap.value(entityID);
|
||||
if (pair) {
|
||||
_filterFunctionMap.remove(entityID);
|
||||
delete pair;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityEditFilters::addEntityFilter(EntityItemID& entityID, QString filterURL) {
|
||||
QUrl scriptURL(filterURL);
|
||||
|
||||
// The following should be abstracted out for use in Agent.cpp (and maybe later AvatarMixer.cpp)
|
||||
if (scriptURL.scheme().isEmpty() || (scriptURL.scheme() == URL_SCHEME_FILE)) {
|
||||
qWarning() << "Cannot load script from local filesystem, because assignment may be on a different computer.";
|
||||
scriptRequestFinished(entityID);
|
||||
return;
|
||||
}
|
||||
// first remove any existing info for this entity
|
||||
removeEntityFilter(entityID);
|
||||
|
||||
auto scriptRequest = ResourceManager::createResourceRequest(this, scriptURL);
|
||||
if (!scriptRequest) {
|
||||
qWarning() << "Could not create ResourceRequest for Entity Edit filter script at" << scriptURL.toString();
|
||||
scriptRequestFinished(entityID);
|
||||
return;
|
||||
}
|
||||
// Agent.cpp sets up a timeout here, but that is unnecessary, as ResourceRequest has its own.
|
||||
connect(scriptRequest, &ResourceRequest::finished, this, [this, &entityID]{ EntityEditFilters::scriptRequestFinished(entityID);} );
|
||||
// FIXME: handle atp rquests setup here. See Agent::requestScript()
|
||||
qInfo() << "Requesting script at URL" << qPrintable(scriptRequest->getUrl().toString());
|
||||
scriptRequest->send();
|
||||
qDebug() << "script request sent";
|
||||
|
||||
}
|
||||
|
||||
// Copied from ScriptEngine.cpp. We should make this a class method for reuse.
|
||||
// Note: I've deliberately stopped short of using ScriptEngine instead of QScriptEngine, as that is out of project scope at this point.
|
||||
static bool hasCorrectSyntax(const QScriptProgram& program) {
|
||||
const auto syntaxCheck = QScriptEngine::checkSyntax(program.sourceCode());
|
||||
if (syntaxCheck.state() != QScriptSyntaxCheckResult::Valid) {
|
||||
const auto error = syntaxCheck.errorMessage();
|
||||
const auto line = QString::number(syntaxCheck.errorLineNumber());
|
||||
const auto column = QString::number(syntaxCheck.errorColumnNumber());
|
||||
const auto message = QString("[SyntaxError] %1 in %2:%3(%4)").arg(error, program.fileName(), line, column);
|
||||
qCritical() << qPrintable(message);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
static bool hadUncaughtExceptions(QScriptEngine& engine, const QString& fileName) {
|
||||
if (engine.hasUncaughtException()) {
|
||||
const auto backtrace = engine.uncaughtExceptionBacktrace();
|
||||
const auto exception = engine.uncaughtException().toString();
|
||||
const auto line = QString::number(engine.uncaughtExceptionLineNumber());
|
||||
engine.clearExceptions();
|
||||
|
||||
static const QString SCRIPT_EXCEPTION_FORMAT = "[UncaughtException] %1 in %2:%3";
|
||||
auto message = QString(SCRIPT_EXCEPTION_FORMAT).arg(exception, fileName, line);
|
||||
if (!backtrace.empty()) {
|
||||
static const auto lineSeparator = "\n ";
|
||||
message += QString("\n[Backtrace]%1%2").arg(lineSeparator, backtrace.join(lineSeparator));
|
||||
}
|
||||
qCritical() << qPrintable(message);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void EntityEditFilters::scriptRequestFinished(EntityItemID& entityID) {
|
||||
qDebug() << "script request completed";
|
||||
auto scriptRequest = qobject_cast<ResourceRequest*>(sender());
|
||||
const QString urlString = scriptRequest->getUrl().toString();
|
||||
if (scriptRequest && scriptRequest->getResult() == ResourceRequest::Success) {
|
||||
auto scriptContents = scriptRequest->getData();
|
||||
qInfo() << "Downloaded script:" << scriptContents;
|
||||
QScriptProgram program(scriptContents, urlString);
|
||||
if (hasCorrectSyntax(program)) {
|
||||
// create a QScriptEngine for this script
|
||||
QScriptEngine* engine = new QScriptEngine();
|
||||
engine->evaluate(scriptContents);
|
||||
if (!hadUncaughtExceptions(*engine, urlString)) {
|
||||
// put the engine in the engine map (so we don't leak them, etc...)
|
||||
_filterScriptEngineMap.insert(entityID, engine);
|
||||
|
||||
// define the uncaughtException function
|
||||
FilterFunctionPair* pair = new FilterFunctionPair();
|
||||
QScriptEngine& engineRef = *engine;
|
||||
pair->second = [this, &engineRef, &urlString]() { return hadUncaughtExceptions(engineRef, urlString); };
|
||||
|
||||
// now get the filter function
|
||||
auto global = engine->globalObject();
|
||||
pair->first = global.property("filter");
|
||||
if (!pair->first.isFunction()) {
|
||||
qDebug() << "Filter function specified but not found. Ignoring filter";
|
||||
return;
|
||||
}
|
||||
_filterFunctionMap.insert(entityID, pair);
|
||||
qDebug() << "script request filter processed";
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (scriptRequest) {
|
||||
qCritical() << "Failed to download script at" << urlString;
|
||||
// See HTTPResourceRequest::onRequestFinished for interpretation of codes. For example, a 404 is code 6 and 403 is 3. A timeout is 2. Go figure.
|
||||
qCritical() << "ResourceRequest error was" << scriptRequest->getResult();
|
||||
} else {
|
||||
qCritical() << "Failed to create script request.";
|
||||
}
|
||||
|
||||
}
|
46
libraries/entities/src/EntityEditFilters.h
Normal file
46
libraries/entities/src/EntityEditFilters.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
//
|
||||
// EntityEditFilters.h
|
||||
// libraries/entities/src
|
||||
//
|
||||
// Created by David Kelly on 2/7/2017.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#ifndef hifi_EntityEditFilters_h
|
||||
#define hifi_EntityEditFilters_h
|
||||
|
||||
#include <QObject>
|
||||
#include <QMap>
|
||||
#include <QScriptValue>
|
||||
#include <QScriptEngine>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "EntityItemID.h"
|
||||
#include "EntityItemProperties.h"
|
||||
|
||||
|
||||
typedef QPair<QScriptValue, std::function<bool()>> FilterFunctionPair;
|
||||
|
||||
class EntityEditFilters : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
EntityEditFilters() {};
|
||||
|
||||
void addEntityFilter(EntityItemID& entityID, QString filterURL);
|
||||
void removeEntityFilter(EntityItemID& entityID);
|
||||
|
||||
QScriptValue filter(glm::vec3& position, EntityItemProperties& propertiesIn, EntityItemProperties& propertiesOut, bool& wasChanged, bool isAdd);
|
||||
|
||||
private slots:
|
||||
void scriptRequestFinished(EntityItemID& entityID);
|
||||
|
||||
private:
|
||||
QMap<EntityItemID, FilterFunctionPair*> _filterFunctionMap;
|
||||
QMap<EntityItemID, QScriptEngine*> _filterScriptEngineMap;
|
||||
};
|
||||
|
||||
#endif //hifi_EntityEditFilters_h
|
Loading…
Reference in a new issue